├── .travis.yml ├── go.mod ├── etc ├── template.go ├── config.go ├── file.go ├── data.go ├── main.go ├── names.go └── names_test.go ├── go.sum ├── .gitignore ├── README.md ├── uintX ├── uintX.yaml ├── domaintree{{.bits}} │ ├── dltree.{{.ext}} │ └── domaintree.{{.ext}} ├── domaintree8 │ ├── dltree.go │ └── domaintree.go ├── domaintree16 │ ├── dltree.go │ └── domaintree.go ├── domaintree32 │ ├── dltree.go │ └── domaintree.go ├── domaintree64 │ ├── dltree.go │ └── domaintree.go ├── strtree{{.bits}} │ └── strtree.{{.ext}} ├── strtree8 │ └── strtree.go ├── strtree16 │ └── strtree.go ├── strtree32 │ └── strtree.go ├── strtree64 │ └── strtree.go ├── iptree{{.bits}} │ ├── iptree.{{.ext}} │ ├── node64s.{{.ext}} │ └── node64.{{.ext}} ├── iptree8 │ ├── iptree.go │ ├── node64s.go │ └── node64.go ├── iptree16 │ ├── iptree.go │ ├── node64s.go │ └── node64.go ├── iptree32 │ ├── iptree.go │ ├── node64s.go │ └── node64.go └── iptree64 │ ├── iptree.go │ └── node64s.go ├── strtree └── strtree.go ├── domain ├── name.go ├── label.go └── name_test.go ├── dltree └── dltree.go └── domaintree └── domaintree.go /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - "1.10" 5 | - "1.11" 6 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/infobloxopen/go-trees 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/pmezard/go-difflib v1.0.0 7 | gopkg.in/yaml.v2 v2.3.0 8 | ) 9 | -------------------------------------------------------------------------------- /etc/template.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "log" 6 | "text/template" 7 | ) 8 | 9 | func executeString(s string, data interface{}) string { 10 | t := template.New("string") 11 | t, err := t.Parse(s) 12 | if err != nil { 13 | log.Fatal(err) 14 | } 15 | 16 | b := new(bytes.Buffer) 17 | if err := t.Execute(b, data); err != nil { 18 | log.Fatal(err) 19 | } 20 | 21 | return b.String() 22 | } 23 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 2 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 3 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 4 | gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= 5 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Vim swap files 2 | [._]*.s[a-v][a-z] 3 | [._]*.sw[a-p] 4 | [._]s[a-v][a-z] 5 | [._]sw[a-p] 6 | 7 | # Binaries for programs and plugins 8 | *.exe 9 | *.dll 10 | *.so 11 | *.dylib 12 | 13 | # Test binary, build with `go test -c` 14 | *.test 15 | 16 | # Output of the go coverage tool, specifically when used with LiteIDE 17 | *.out 18 | 19 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 20 | .glide/ 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-trees [![Build Status](https://travis-ci.org/infobloxopen/go-trees.svg?branch=master)](https://travis-ci.org/infobloxopen/go-trees.svg?branch=master) [![GoDoc](https://godoc.org/github.com/infobloxopen/go-trees?status.svg)](https://godoc.org/github.com/infobloxopen/go-trees) [![Go Report Card](https://goreportcard.com/badge/github.com/infobloxopen/go-trees)](https://goreportcard.com/report/github.com/infobloxopen/go-trees) 2 | 3 | go packages for radix and other trees 4 | -------------------------------------------------------------------------------- /etc/config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "log" 6 | ) 7 | 8 | type config struct { 9 | template string 10 | data string 11 | selector string 12 | } 13 | 14 | var conf config 15 | 16 | func parseFlags() { 17 | flag.StringVar(&conf.template, "t", "", "path to template (required)") 18 | flag.StringVar(&conf.data, "d", "", "path to data") 19 | flag.StringVar(&conf.selector, "s", "", "path in YAML to get data") 20 | 21 | flag.Parse() 22 | 23 | if len(conf.template) <= 0 { 24 | log.Fatal("No path to template - nothing to execute") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /etc/file.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "text/template" 7 | ) 8 | 9 | func executeDir(name string) { 10 | if err := os.MkdirAll(name, 0755); err != nil { 11 | log.Fatal(err) 12 | } 13 | } 14 | 15 | func executeFile(out, in string, data interface{}) { 16 | t, err := template.ParseFiles(in) 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | 21 | f, err := os.Create(out) 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | defer f.Close() 26 | 27 | if err := t.Execute(f, data); err != nil { 28 | log.Fatal(err) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /uintX/uintX.yaml: -------------------------------------------------------------------------------- 1 | uint8: 2 | bits: 8 3 | ext: go 4 | warning: "!!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint8 -d uintX.yaml -t ./tree\\{\\{.bits\\}\\}" 5 | 6 | uint16: 7 | bits: 16 8 | ext: go 9 | warning: "!!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint16 -d uintX.yaml -t ./tree\\{\\{.bits\\}\\}" 10 | 11 | uint32: 12 | bits: 32 13 | ext: go 14 | warning: "!!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint32 -d uintX.yaml -t ./tree\\{\\{.bits\\}\\}" 15 | 16 | uint64: 17 | bits: 64 18 | ext: go 19 | warning: "!!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint64 -d uintX.yaml -t ./tree\\{\\{.bits\\}\\}" 20 | -------------------------------------------------------------------------------- /etc/data.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "strings" 8 | 9 | "gopkg.in/yaml.v2" 10 | ) 11 | 12 | func load(name string, path string) interface{} { 13 | f, err := os.Open(name) 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | defer f.Close() 18 | 19 | d := yaml.NewDecoder(f) 20 | 21 | m := make(map[interface{}]interface{}) 22 | if err := d.Decode(m); err != nil { 23 | log.Fatalf("can't decode data from %q: %s", name, err) 24 | } 25 | 26 | out, err := sel(path, m) 27 | if err != nil { 28 | log.Fatalf("no data for %q in %q: %s", path, name, err) 29 | } 30 | 31 | return out 32 | } 33 | 34 | func sel(path string, m map[interface{}]interface{}) (interface{}, error) { 35 | if len(path) > 0 { 36 | parts := strings.SplitN(path, ".", 2) 37 | v, ok := m[parts[0]] 38 | if !ok { 39 | return nil, fmt.Errorf("missing %q", parts[0]) 40 | } 41 | 42 | if len(parts) > 1 { 43 | m, ok := v.(map[interface{}]interface{}) 44 | if !ok { 45 | return nil, fmt.Errorf("can't go deeper than %q", parts[0]) 46 | } 47 | 48 | return sel(parts[1], m) 49 | } 50 | 51 | return v, nil 52 | } 53 | 54 | return m, nil 55 | } 56 | -------------------------------------------------------------------------------- /etc/main.go: -------------------------------------------------------------------------------- 1 | // ETC (Execute Template Catalog) executes all templates recursively in a given directory. 2 | package main 3 | 4 | import ( 5 | "io/ioutil" 6 | "log" 7 | "os" 8 | "path" 9 | "path/filepath" 10 | ) 11 | 12 | func main() { 13 | parseFlags() 14 | execute(conf.template, load(conf.data, conf.selector), makePrefix(conf.template)) 15 | } 16 | 17 | func execute(name string, data interface{}, prefix []string) { 18 | absName, err := filepath.Abs(name) 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | 23 | relName := getRelName(absName, prefix) 24 | log.Printf("executing %q", relName) 25 | 26 | fi, err := os.Stat(absName) 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | 31 | newName := executeString(absName, data) 32 | if newName == absName { 33 | log.Fatalf("instance name is the same as template name %q", newName) 34 | } 35 | 36 | if fi.IsDir() { 37 | log.Printf("creating directory %q -> %q", relName, getRelName(newName, prefix)) 38 | executeDir(newName) 39 | 40 | lst, err := ioutil.ReadDir(absName) 41 | if err != nil { 42 | log.Fatal(err) 43 | } 44 | 45 | for _, item := range lst { 46 | execute(path.Join(absName, item.Name()), data, prefix) 47 | } 48 | } else { 49 | log.Printf("creating file %q -> %q", relName, getRelName(newName, prefix)) 50 | executeFile(newName, absName, data) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /etc/names.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "path" 6 | "path/filepath" 7 | ) 8 | 9 | func makePrefix(p string) []string { 10 | a, err := filepath.Abs(p) 11 | if err != nil { 12 | log.Fatal(err) 13 | } 14 | 15 | d, f := filepath.Split(a) 16 | if len(f) <= 0 { 17 | log.Fatalf("can't execute template at %q (%q) as it has no base name", p, a) 18 | } 19 | 20 | return fullSplit(d) 21 | } 22 | 23 | func getRelName(p string, prefix []string) string { 24 | seq := fullSplit(p) 25 | if hasPrefix(seq, prefix) { 26 | return path.Join(seq[len(prefix):]...) 27 | } 28 | 29 | return filepath.Base(p) 30 | } 31 | 32 | const preAllocStrings = 10 33 | 34 | func fullSplit(p string) []string { 35 | d := filepath.Clean(p) 36 | 37 | out := make([]string, preAllocStrings) 38 | i := preAllocStrings 39 | for { 40 | i-- 41 | if i < 0 { 42 | out = append(make([]string, preAllocStrings), out...) 43 | i = preAllocStrings 44 | continue 45 | } 46 | 47 | parent, f := filepath.Split(d) 48 | if len(f) <= 0 { 49 | out[i] = filepath.Clean(parent) 50 | break 51 | } 52 | 53 | if len(parent) <= 0 { 54 | out[i] = f 55 | break 56 | } 57 | 58 | out[i] = f 59 | 60 | d = filepath.Clean(parent) 61 | } 62 | 63 | return out[i:] 64 | } 65 | 66 | func hasPrefix(p, prefix []string) bool { 67 | if len(p) < len(prefix) { 68 | return false 69 | } 70 | 71 | for i, item := range prefix { 72 | if p[i] != item { 73 | return false 74 | } 75 | } 76 | 77 | return true 78 | } 79 | -------------------------------------------------------------------------------- /etc/names_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "path" 5 | "path/filepath" 6 | "testing" 7 | ) 8 | 9 | func TestNameGetRelName(t *testing.T) { 10 | e := filepath.FromSlash("d/e") 11 | s := getRelName( 12 | filepath.FromSlash("/a/b/c/d/e"), 13 | []string{filepath.FromSlash("/"), "a", "b", "c"}, 14 | ) 15 | 16 | if s != e { 17 | t.Errorf("expected %q as relative path but got %q", e, s) 18 | } 19 | 20 | e = filepath.FromSlash("e") 21 | s = getRelName( 22 | filepath.FromSlash("/a/b/c/d/e"), 23 | []string{filepath.FromSlash("/"), "a", "B", "c"}, 24 | ) 25 | 26 | if s != e { 27 | t.Errorf("expected %q as relative path but got %q", e, s) 28 | } 29 | } 30 | 31 | func TestNameFullSplit(t *testing.T) { 32 | assertPathSlice(t, "3-level abs path", 33 | fullSplit(filepath.FromSlash("/a/b/c")), 34 | filepath.FromSlash("/"), "a", "b", "c", 35 | ) 36 | 37 | assertPathSlice(t, "11-level abs path", 38 | fullSplit(filepath.FromSlash("/a/b/c/d/e/f/g/h/i/j/k")), 39 | filepath.FromSlash("/"), "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", 40 | ) 41 | 42 | assertPathSlice(t, "rel path", 43 | fullSplit(filepath.FromSlash("a/b/c")), 44 | "a", "b", "c", 45 | ) 46 | 47 | assertPathSlice(t, "dirty path", 48 | fullSplit(filepath.FromSlash("a//b/./c/")), 49 | "a", "b", "c", 50 | ) 51 | } 52 | 53 | func TestNameHasPrefix(t *testing.T) { 54 | p := []string{"/", "a", "b", "c", "d"} 55 | prefix := []string{"/", "a", "b", "c"} 56 | 57 | if !hasPrefix(p, prefix) { 58 | t.Errorf("expected %q to have prefix %q", path.Join(p...), path.Join(prefix...)) 59 | } 60 | 61 | p = []string{"/", "a", "b"} 62 | if hasPrefix(p, prefix) { 63 | t.Errorf("expected %q not to have prefix %q", path.Join(p...), path.Join(prefix...)) 64 | } 65 | 66 | p = []string{"/", "a", "B", "c", "d"} 67 | if hasPrefix(p, prefix) { 68 | t.Errorf("expected %q not to have prefix %q", path.Join(p...), path.Join(prefix...)) 69 | } 70 | } 71 | 72 | func assertPathSlice(t *testing.T, desc string, v []string, e ...string) { 73 | if len(v) != len(e) { 74 | t.Errorf("expected %q for %s but got %q", path.Join(e...), desc, path.Join(v...)) 75 | } 76 | 77 | for i, item := range e { 78 | if v[i] != item { 79 | t.Errorf("expected %q for %s but got %q", path.Join(e...), desc, path.Join(v...)) 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /uintX/domaintree{{.bits}}/dltree.{{.ext}}: -------------------------------------------------------------------------------- 1 | package domaintree{{.bits}} 2 | 3 | // {{.warning}} 4 | 5 | import "github.com/infobloxopen/go-trees/domain" 6 | 7 | type labelTree struct { 8 | root *node 9 | } 10 | 11 | type labelPair struct { 12 | Key string 13 | Value *Node 14 | } 15 | 16 | func newLabelTree() *labelTree { 17 | return new(labelTree) 18 | } 19 | 20 | func (t *labelTree) insert(key string, value *Node) *labelTree { 21 | var ( 22 | n *node 23 | ) 24 | 25 | if t != nil { 26 | n = t.root 27 | } 28 | 29 | dl, _ := domain.MakeLabel(key) 30 | return &labelTree{root: n.insert(dl, value)} 31 | } 32 | 33 | func (t *labelTree) rawInsert(key string, value *Node) *labelTree { 34 | var ( 35 | n *node 36 | ) 37 | 38 | if t != nil { 39 | n = t.root 40 | } 41 | 42 | return &labelTree{root: n.insert(key, value)} 43 | } 44 | 45 | func (t *labelTree) inplaceInsert(key string, value *Node) { 46 | dl, _ := domain.MakeLabel(key) 47 | t.root = t.root.inplaceInsert(dl, value) 48 | } 49 | 50 | func (t *labelTree) rawInplaceInsert(key string, value *Node) { 51 | t.root = t.root.inplaceInsert(key, value) 52 | } 53 | 54 | func (t *labelTree) get(key string) (*Node, bool) { 55 | if t == nil { 56 | return nil, false 57 | } 58 | 59 | dl, _ := domain.MakeLabel(key) 60 | return t.root.get(dl) 61 | } 62 | 63 | func (t *labelTree) rawGet(key string) (*Node, bool) { 64 | if t == nil { 65 | return nil, false 66 | } 67 | 68 | return t.root.get(key) 69 | } 70 | 71 | func (t *labelTree) enumerate() chan labelPair { 72 | ch := make(chan labelPair) 73 | 74 | go func() { 75 | defer close(ch) 76 | 77 | if t == nil { 78 | return 79 | } 80 | 81 | t.root.enumerate(ch) 82 | }() 83 | 84 | return ch 85 | } 86 | 87 | func (t *labelTree) rawEnumerate() chan labelPair { 88 | ch := make(chan labelPair) 89 | 90 | go func() { 91 | defer close(ch) 92 | 93 | if t == nil { 94 | return 95 | } 96 | 97 | t.root.rawEnumerate(ch) 98 | }() 99 | 100 | return ch 101 | } 102 | 103 | func (t *labelTree) del(key string) (*labelTree, bool) { 104 | if t == nil { 105 | return nil, false 106 | } 107 | 108 | dl, _ := domain.MakeLabel(key) 109 | root, ok := t.root.del(dl) 110 | return &labelTree{root: root}, ok 111 | } 112 | 113 | func (t *labelTree) rawDel(key string) (*labelTree, bool) { 114 | if t == nil { 115 | return nil, false 116 | } 117 | 118 | root, ok := t.root.del(key) 119 | return &labelTree{root: root}, ok 120 | } 121 | 122 | func (t *labelTree) isEmpty() bool { 123 | return t == nil || t.root == nil 124 | } 125 | 126 | func (t *labelTree) dot() string { 127 | body := "" 128 | 129 | if t != nil { 130 | body = t.root.dot() 131 | } 132 | 133 | return "digraph d {\n" + body + "}\n" 134 | } 135 | -------------------------------------------------------------------------------- /uintX/domaintree8/dltree.go: -------------------------------------------------------------------------------- 1 | package domaintree8 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint8 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import "github.com/infobloxopen/go-trees/domain" 6 | 7 | type labelTree struct { 8 | root *node 9 | } 10 | 11 | type labelPair struct { 12 | Key string 13 | Value *Node 14 | } 15 | 16 | func newLabelTree() *labelTree { 17 | return new(labelTree) 18 | } 19 | 20 | func (t *labelTree) insert(key string, value *Node) *labelTree { 21 | var ( 22 | n *node 23 | ) 24 | 25 | if t != nil { 26 | n = t.root 27 | } 28 | 29 | dl, _ := domain.MakeLabel(key) 30 | return &labelTree{root: n.insert(dl, value)} 31 | } 32 | 33 | func (t *labelTree) rawInsert(key string, value *Node) *labelTree { 34 | var ( 35 | n *node 36 | ) 37 | 38 | if t != nil { 39 | n = t.root 40 | } 41 | 42 | return &labelTree{root: n.insert(key, value)} 43 | } 44 | 45 | func (t *labelTree) inplaceInsert(key string, value *Node) { 46 | dl, _ := domain.MakeLabel(key) 47 | t.root = t.root.inplaceInsert(dl, value) 48 | } 49 | 50 | func (t *labelTree) rawInplaceInsert(key string, value *Node) { 51 | t.root = t.root.inplaceInsert(key, value) 52 | } 53 | 54 | func (t *labelTree) get(key string) (*Node, bool) { 55 | if t == nil { 56 | return nil, false 57 | } 58 | 59 | dl, _ := domain.MakeLabel(key) 60 | return t.root.get(dl) 61 | } 62 | 63 | func (t *labelTree) rawGet(key string) (*Node, bool) { 64 | if t == nil { 65 | return nil, false 66 | } 67 | 68 | return t.root.get(key) 69 | } 70 | 71 | func (t *labelTree) enumerate() chan labelPair { 72 | ch := make(chan labelPair) 73 | 74 | go func() { 75 | defer close(ch) 76 | 77 | if t == nil { 78 | return 79 | } 80 | 81 | t.root.enumerate(ch) 82 | }() 83 | 84 | return ch 85 | } 86 | 87 | func (t *labelTree) rawEnumerate() chan labelPair { 88 | ch := make(chan labelPair) 89 | 90 | go func() { 91 | defer close(ch) 92 | 93 | if t == nil { 94 | return 95 | } 96 | 97 | t.root.rawEnumerate(ch) 98 | }() 99 | 100 | return ch 101 | } 102 | 103 | func (t *labelTree) del(key string) (*labelTree, bool) { 104 | if t == nil { 105 | return nil, false 106 | } 107 | 108 | dl, _ := domain.MakeLabel(key) 109 | root, ok := t.root.del(dl) 110 | return &labelTree{root: root}, ok 111 | } 112 | 113 | func (t *labelTree) rawDel(key string) (*labelTree, bool) { 114 | if t == nil { 115 | return nil, false 116 | } 117 | 118 | root, ok := t.root.del(key) 119 | return &labelTree{root: root}, ok 120 | } 121 | 122 | func (t *labelTree) isEmpty() bool { 123 | return t == nil || t.root == nil 124 | } 125 | 126 | func (t *labelTree) dot() string { 127 | body := "" 128 | 129 | if t != nil { 130 | body = t.root.dot() 131 | } 132 | 133 | return "digraph d {\n" + body + "}\n" 134 | } 135 | -------------------------------------------------------------------------------- /uintX/domaintree16/dltree.go: -------------------------------------------------------------------------------- 1 | package domaintree16 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint16 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import "github.com/infobloxopen/go-trees/domain" 6 | 7 | type labelTree struct { 8 | root *node 9 | } 10 | 11 | type labelPair struct { 12 | Key string 13 | Value *Node 14 | } 15 | 16 | func newLabelTree() *labelTree { 17 | return new(labelTree) 18 | } 19 | 20 | func (t *labelTree) insert(key string, value *Node) *labelTree { 21 | var ( 22 | n *node 23 | ) 24 | 25 | if t != nil { 26 | n = t.root 27 | } 28 | 29 | dl, _ := domain.MakeLabel(key) 30 | return &labelTree{root: n.insert(dl, value)} 31 | } 32 | 33 | func (t *labelTree) rawInsert(key string, value *Node) *labelTree { 34 | var ( 35 | n *node 36 | ) 37 | 38 | if t != nil { 39 | n = t.root 40 | } 41 | 42 | return &labelTree{root: n.insert(key, value)} 43 | } 44 | 45 | func (t *labelTree) inplaceInsert(key string, value *Node) { 46 | dl, _ := domain.MakeLabel(key) 47 | t.root = t.root.inplaceInsert(dl, value) 48 | } 49 | 50 | func (t *labelTree) rawInplaceInsert(key string, value *Node) { 51 | t.root = t.root.inplaceInsert(key, value) 52 | } 53 | 54 | func (t *labelTree) get(key string) (*Node, bool) { 55 | if t == nil { 56 | return nil, false 57 | } 58 | 59 | dl, _ := domain.MakeLabel(key) 60 | return t.root.get(dl) 61 | } 62 | 63 | func (t *labelTree) rawGet(key string) (*Node, bool) { 64 | if t == nil { 65 | return nil, false 66 | } 67 | 68 | return t.root.get(key) 69 | } 70 | 71 | func (t *labelTree) enumerate() chan labelPair { 72 | ch := make(chan labelPair) 73 | 74 | go func() { 75 | defer close(ch) 76 | 77 | if t == nil { 78 | return 79 | } 80 | 81 | t.root.enumerate(ch) 82 | }() 83 | 84 | return ch 85 | } 86 | 87 | func (t *labelTree) rawEnumerate() chan labelPair { 88 | ch := make(chan labelPair) 89 | 90 | go func() { 91 | defer close(ch) 92 | 93 | if t == nil { 94 | return 95 | } 96 | 97 | t.root.rawEnumerate(ch) 98 | }() 99 | 100 | return ch 101 | } 102 | 103 | func (t *labelTree) del(key string) (*labelTree, bool) { 104 | if t == nil { 105 | return nil, false 106 | } 107 | 108 | dl, _ := domain.MakeLabel(key) 109 | root, ok := t.root.del(dl) 110 | return &labelTree{root: root}, ok 111 | } 112 | 113 | func (t *labelTree) rawDel(key string) (*labelTree, bool) { 114 | if t == nil { 115 | return nil, false 116 | } 117 | 118 | root, ok := t.root.del(key) 119 | return &labelTree{root: root}, ok 120 | } 121 | 122 | func (t *labelTree) isEmpty() bool { 123 | return t == nil || t.root == nil 124 | } 125 | 126 | func (t *labelTree) dot() string { 127 | body := "" 128 | 129 | if t != nil { 130 | body = t.root.dot() 131 | } 132 | 133 | return "digraph d {\n" + body + "}\n" 134 | } 135 | -------------------------------------------------------------------------------- /uintX/domaintree32/dltree.go: -------------------------------------------------------------------------------- 1 | package domaintree32 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint32 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import "github.com/infobloxopen/go-trees/domain" 6 | 7 | type labelTree struct { 8 | root *node 9 | } 10 | 11 | type labelPair struct { 12 | Key string 13 | Value *Node 14 | } 15 | 16 | func newLabelTree() *labelTree { 17 | return new(labelTree) 18 | } 19 | 20 | func (t *labelTree) insert(key string, value *Node) *labelTree { 21 | var ( 22 | n *node 23 | ) 24 | 25 | if t != nil { 26 | n = t.root 27 | } 28 | 29 | dl, _ := domain.MakeLabel(key) 30 | return &labelTree{root: n.insert(dl, value)} 31 | } 32 | 33 | func (t *labelTree) rawInsert(key string, value *Node) *labelTree { 34 | var ( 35 | n *node 36 | ) 37 | 38 | if t != nil { 39 | n = t.root 40 | } 41 | 42 | return &labelTree{root: n.insert(key, value)} 43 | } 44 | 45 | func (t *labelTree) inplaceInsert(key string, value *Node) { 46 | dl, _ := domain.MakeLabel(key) 47 | t.root = t.root.inplaceInsert(dl, value) 48 | } 49 | 50 | func (t *labelTree) rawInplaceInsert(key string, value *Node) { 51 | t.root = t.root.inplaceInsert(key, value) 52 | } 53 | 54 | func (t *labelTree) get(key string) (*Node, bool) { 55 | if t == nil { 56 | return nil, false 57 | } 58 | 59 | dl, _ := domain.MakeLabel(key) 60 | return t.root.get(dl) 61 | } 62 | 63 | func (t *labelTree) rawGet(key string) (*Node, bool) { 64 | if t == nil { 65 | return nil, false 66 | } 67 | 68 | return t.root.get(key) 69 | } 70 | 71 | func (t *labelTree) enumerate() chan labelPair { 72 | ch := make(chan labelPair) 73 | 74 | go func() { 75 | defer close(ch) 76 | 77 | if t == nil { 78 | return 79 | } 80 | 81 | t.root.enumerate(ch) 82 | }() 83 | 84 | return ch 85 | } 86 | 87 | func (t *labelTree) rawEnumerate() chan labelPair { 88 | ch := make(chan labelPair) 89 | 90 | go func() { 91 | defer close(ch) 92 | 93 | if t == nil { 94 | return 95 | } 96 | 97 | t.root.rawEnumerate(ch) 98 | }() 99 | 100 | return ch 101 | } 102 | 103 | func (t *labelTree) del(key string) (*labelTree, bool) { 104 | if t == nil { 105 | return nil, false 106 | } 107 | 108 | dl, _ := domain.MakeLabel(key) 109 | root, ok := t.root.del(dl) 110 | return &labelTree{root: root}, ok 111 | } 112 | 113 | func (t *labelTree) rawDel(key string) (*labelTree, bool) { 114 | if t == nil { 115 | return nil, false 116 | } 117 | 118 | root, ok := t.root.del(key) 119 | return &labelTree{root: root}, ok 120 | } 121 | 122 | func (t *labelTree) isEmpty() bool { 123 | return t == nil || t.root == nil 124 | } 125 | 126 | func (t *labelTree) dot() string { 127 | body := "" 128 | 129 | if t != nil { 130 | body = t.root.dot() 131 | } 132 | 133 | return "digraph d {\n" + body + "}\n" 134 | } 135 | -------------------------------------------------------------------------------- /uintX/domaintree64/dltree.go: -------------------------------------------------------------------------------- 1 | package domaintree64 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint64 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import "github.com/infobloxopen/go-trees/domain" 6 | 7 | type labelTree struct { 8 | root *node 9 | } 10 | 11 | type labelPair struct { 12 | Key string 13 | Value *Node 14 | } 15 | 16 | func newLabelTree() *labelTree { 17 | return new(labelTree) 18 | } 19 | 20 | func (t *labelTree) insert(key string, value *Node) *labelTree { 21 | var ( 22 | n *node 23 | ) 24 | 25 | if t != nil { 26 | n = t.root 27 | } 28 | 29 | dl, _ := domain.MakeLabel(key) 30 | return &labelTree{root: n.insert(dl, value)} 31 | } 32 | 33 | func (t *labelTree) rawInsert(key string, value *Node) *labelTree { 34 | var ( 35 | n *node 36 | ) 37 | 38 | if t != nil { 39 | n = t.root 40 | } 41 | 42 | return &labelTree{root: n.insert(key, value)} 43 | } 44 | 45 | func (t *labelTree) inplaceInsert(key string, value *Node) { 46 | dl, _ := domain.MakeLabel(key) 47 | t.root = t.root.inplaceInsert(dl, value) 48 | } 49 | 50 | func (t *labelTree) rawInplaceInsert(key string, value *Node) { 51 | t.root = t.root.inplaceInsert(key, value) 52 | } 53 | 54 | func (t *labelTree) get(key string) (*Node, bool) { 55 | if t == nil { 56 | return nil, false 57 | } 58 | 59 | dl, _ := domain.MakeLabel(key) 60 | return t.root.get(dl) 61 | } 62 | 63 | func (t *labelTree) rawGet(key string) (*Node, bool) { 64 | if t == nil { 65 | return nil, false 66 | } 67 | 68 | return t.root.get(key) 69 | } 70 | 71 | func (t *labelTree) enumerate() chan labelPair { 72 | ch := make(chan labelPair) 73 | 74 | go func() { 75 | defer close(ch) 76 | 77 | if t == nil { 78 | return 79 | } 80 | 81 | t.root.enumerate(ch) 82 | }() 83 | 84 | return ch 85 | } 86 | 87 | func (t *labelTree) rawEnumerate() chan labelPair { 88 | ch := make(chan labelPair) 89 | 90 | go func() { 91 | defer close(ch) 92 | 93 | if t == nil { 94 | return 95 | } 96 | 97 | t.root.rawEnumerate(ch) 98 | }() 99 | 100 | return ch 101 | } 102 | 103 | func (t *labelTree) del(key string) (*labelTree, bool) { 104 | if t == nil { 105 | return nil, false 106 | } 107 | 108 | dl, _ := domain.MakeLabel(key) 109 | root, ok := t.root.del(dl) 110 | return &labelTree{root: root}, ok 111 | } 112 | 113 | func (t *labelTree) rawDel(key string) (*labelTree, bool) { 114 | if t == nil { 115 | return nil, false 116 | } 117 | 118 | root, ok := t.root.del(key) 119 | return &labelTree{root: root}, ok 120 | } 121 | 122 | func (t *labelTree) isEmpty() bool { 123 | return t == nil || t.root == nil 124 | } 125 | 126 | func (t *labelTree) dot() string { 127 | body := "" 128 | 129 | if t != nil { 130 | body = t.root.dot() 131 | } 132 | 133 | return "digraph d {\n" + body + "}\n" 134 | } 135 | -------------------------------------------------------------------------------- /strtree/strtree.go: -------------------------------------------------------------------------------- 1 | // Package strtree implements red-black tree for key value pairs with string keys and custom comparison. 2 | package strtree 3 | 4 | import "strings" 5 | 6 | // Compare defines function interface for custom comparison. Function implementing the interface should return value less than zero if its first argument precedes second one, zero if both are equal and positive if the second precedes. 7 | type Compare func(a, b string) int 8 | 9 | // Tree is a red-black tree for key-value pairs where key is string. 10 | type Tree struct { 11 | root *node 12 | compare Compare 13 | } 14 | 15 | // Pair is a key-value pair representing tree node content. 16 | type Pair struct { 17 | Key string 18 | Value interface{} 19 | } 20 | 21 | // NewTree creates empty tree with default comparison operation (strings.Compare). 22 | func NewTree() *Tree { 23 | return &Tree{compare: strings.Compare} 24 | } 25 | 26 | // NewTreeWithCustomComparison creates empty tree with given comparison operation. 27 | func NewTreeWithCustomComparison(compare Compare) *Tree { 28 | return &Tree{compare: compare} 29 | } 30 | 31 | // Insert puts given key-value pair to the tree and returns pointer to new root. 32 | func (t *Tree) Insert(key string, value interface{}) *Tree { 33 | var ( 34 | n *node 35 | c Compare 36 | ) 37 | 38 | if t == nil { 39 | c = strings.Compare 40 | } else { 41 | n = t.root 42 | c = t.compare 43 | } 44 | 45 | return &Tree{root: n.insert(key, value, c), compare: c} 46 | } 47 | 48 | // InplaceInsert inserts or replaces given key-value pair in the tree. The method inserts data directly to current tree so make sure you have exclusive access to it. 49 | func (t *Tree) InplaceInsert(key string, value interface{}) { 50 | t.root = t.root.inplaceInsert(key, value, t.compare) 51 | } 52 | 53 | // Get returns value by given key. 54 | func (t *Tree) Get(key string) (interface{}, bool) { 55 | if t == nil { 56 | return nil, false 57 | } 58 | 59 | return t.root.get(key, t.compare) 60 | } 61 | 62 | // Enumerate returns channel which is populated by key pair values in order of keys. 63 | func (t *Tree) Enumerate() chan Pair { 64 | ch := make(chan Pair) 65 | 66 | go func() { 67 | defer close(ch) 68 | 69 | if t == nil { 70 | return 71 | } 72 | 73 | t.root.enumerate(ch) 74 | }() 75 | 76 | return ch 77 | } 78 | 79 | // Delete removes node by given key. It returns copy of tree and true if node has been indeed deleted otherwise original tree and false. 80 | func (t *Tree) Delete(key string) (*Tree, bool) { 81 | if t == nil { 82 | return nil, false 83 | } 84 | 85 | c := t.compare 86 | root, ok := t.root.del(key, c) 87 | return &Tree{root: root, compare: c}, ok 88 | } 89 | 90 | // IsEmpty returns true if given tree has no nodes. 91 | func (t *Tree) IsEmpty() bool { 92 | return t == nil || t.root == nil 93 | } 94 | 95 | // Dot dumps tree to Graphviz .dot format. 96 | func (t *Tree) Dot() string { 97 | body := "" 98 | 99 | if t != nil { 100 | body = t.root.dot() 101 | } 102 | 103 | return "digraph d {\n" + body + "}\n" 104 | } 105 | -------------------------------------------------------------------------------- /uintX/strtree{{.bits}}/strtree.{{.ext}}: -------------------------------------------------------------------------------- 1 | // Package strtree{{.bits}} implements red-black tree for key value pairs with string keys, uint{{.bits}} values and custom comparison. 2 | package strtree{{.bits}} 3 | 4 | // {{.warning}} 5 | 6 | import "strings" 7 | 8 | // Compare defines function interface for custom comparison. Function implementing the interface should return value less than zero if its first argument precedes second one, zero if both are equal and positive if the second precedes. 9 | type Compare func(a, b string) int 10 | 11 | // Tree is a red-black tree for key-value pairs where key is string. 12 | type Tree struct { 13 | root *node 14 | compare Compare 15 | } 16 | 17 | // Pair is a key-value pair representing tree node content. 18 | type Pair struct { 19 | Key string 20 | Value uint{{.bits}} 21 | } 22 | 23 | // NewTree creates empty tree with default comparison operation (strings.Compare). 24 | func NewTree() *Tree { 25 | return &Tree{compare: strings.Compare} 26 | } 27 | 28 | // NewTreeWithCustomComparison creates empty tree with given comparison operation. 29 | func NewTreeWithCustomComparison(compare Compare) *Tree { 30 | return &Tree{compare: compare} 31 | } 32 | 33 | // Insert puts given key-value pair to the tree and returns pointer to new root. 34 | func (t *Tree) Insert(key string, value uint{{.bits}}) *Tree { 35 | var ( 36 | n *node 37 | c Compare 38 | ) 39 | 40 | if t == nil { 41 | c = strings.Compare 42 | } else { 43 | n = t.root 44 | c = t.compare 45 | } 46 | 47 | return &Tree{root: n.insert(key, value, c), compare: c} 48 | } 49 | 50 | // InplaceInsert inserts or replaces given key-value pair in the tree. The method inserts data directly to current tree so make sure you have exclusive access to it. 51 | func (t *Tree) InplaceInsert(key string, value uint{{.bits}}) { 52 | t.root = t.root.inplaceInsert(key, value, t.compare) 53 | } 54 | 55 | // Get returns value by given key. 56 | func (t *Tree) Get(key string) (uint{{.bits}}, bool) { 57 | if t == nil { 58 | return 0, false 59 | } 60 | 61 | return t.root.get(key, t.compare) 62 | } 63 | 64 | // Enumerate returns channel which is populated by key pair values in order of keys. 65 | func (t *Tree) Enumerate() chan Pair { 66 | ch := make(chan Pair) 67 | 68 | go func() { 69 | defer close(ch) 70 | 71 | if t == nil { 72 | return 73 | } 74 | 75 | t.root.enumerate(ch) 76 | }() 77 | 78 | return ch 79 | } 80 | 81 | // Delete removes node by given key. It returns copy of tree and true if node has been indeed deleted otherwise original tree and false. 82 | func (t *Tree) Delete(key string) (*Tree, bool) { 83 | if t == nil { 84 | return nil, false 85 | } 86 | 87 | c := t.compare 88 | root, ok := t.root.del(key, c) 89 | return &Tree{root: root, compare: c}, ok 90 | } 91 | 92 | // IsEmpty returns true if given tree has no nodes. 93 | func (t *Tree) IsEmpty() bool { 94 | return t == nil || t.root == nil 95 | } 96 | 97 | // Dot dumps tree to Graphviz .dot format. 98 | func (t *Tree) Dot() string { 99 | body := "" 100 | 101 | if t != nil { 102 | body = t.root.dot() 103 | } 104 | 105 | return "digraph d {\n" + body + "}\n" 106 | } 107 | -------------------------------------------------------------------------------- /uintX/strtree8/strtree.go: -------------------------------------------------------------------------------- 1 | // Package strtree8 implements red-black tree for key value pairs with string keys, uint8 values and custom comparison. 2 | package strtree8 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint8 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import "strings" 7 | 8 | // Compare defines function interface for custom comparison. Function implementing the interface should return value less than zero if its first argument precedes second one, zero if both are equal and positive if the second precedes. 9 | type Compare func(a, b string) int 10 | 11 | // Tree is a red-black tree for key-value pairs where key is string. 12 | type Tree struct { 13 | root *node 14 | compare Compare 15 | } 16 | 17 | // Pair is a key-value pair representing tree node content. 18 | type Pair struct { 19 | Key string 20 | Value uint8 21 | } 22 | 23 | // NewTree creates empty tree with default comparison operation (strings.Compare). 24 | func NewTree() *Tree { 25 | return &Tree{compare: strings.Compare} 26 | } 27 | 28 | // NewTreeWithCustomComparison creates empty tree with given comparison operation. 29 | func NewTreeWithCustomComparison(compare Compare) *Tree { 30 | return &Tree{compare: compare} 31 | } 32 | 33 | // Insert puts given key-value pair to the tree and returns pointer to new root. 34 | func (t *Tree) Insert(key string, value uint8) *Tree { 35 | var ( 36 | n *node 37 | c Compare 38 | ) 39 | 40 | if t == nil { 41 | c = strings.Compare 42 | } else { 43 | n = t.root 44 | c = t.compare 45 | } 46 | 47 | return &Tree{root: n.insert(key, value, c), compare: c} 48 | } 49 | 50 | // InplaceInsert inserts or replaces given key-value pair in the tree. The method inserts data directly to current tree so make sure you have exclusive access to it. 51 | func (t *Tree) InplaceInsert(key string, value uint8) { 52 | t.root = t.root.inplaceInsert(key, value, t.compare) 53 | } 54 | 55 | // Get returns value by given key. 56 | func (t *Tree) Get(key string) (uint8, bool) { 57 | if t == nil { 58 | return 0, false 59 | } 60 | 61 | return t.root.get(key, t.compare) 62 | } 63 | 64 | // Enumerate returns channel which is populated by key pair values in order of keys. 65 | func (t *Tree) Enumerate() chan Pair { 66 | ch := make(chan Pair) 67 | 68 | go func() { 69 | defer close(ch) 70 | 71 | if t == nil { 72 | return 73 | } 74 | 75 | t.root.enumerate(ch) 76 | }() 77 | 78 | return ch 79 | } 80 | 81 | // Delete removes node by given key. It returns copy of tree and true if node has been indeed deleted otherwise original tree and false. 82 | func (t *Tree) Delete(key string) (*Tree, bool) { 83 | if t == nil { 84 | return nil, false 85 | } 86 | 87 | c := t.compare 88 | root, ok := t.root.del(key, c) 89 | return &Tree{root: root, compare: c}, ok 90 | } 91 | 92 | // IsEmpty returns true if given tree has no nodes. 93 | func (t *Tree) IsEmpty() bool { 94 | return t == nil || t.root == nil 95 | } 96 | 97 | // Dot dumps tree to Graphviz .dot format. 98 | func (t *Tree) Dot() string { 99 | body := "" 100 | 101 | if t != nil { 102 | body = t.root.dot() 103 | } 104 | 105 | return "digraph d {\n" + body + "}\n" 106 | } 107 | -------------------------------------------------------------------------------- /uintX/strtree16/strtree.go: -------------------------------------------------------------------------------- 1 | // Package strtree16 implements red-black tree for key value pairs with string keys, uint16 values and custom comparison. 2 | package strtree16 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint16 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import "strings" 7 | 8 | // Compare defines function interface for custom comparison. Function implementing the interface should return value less than zero if its first argument precedes second one, zero if both are equal and positive if the second precedes. 9 | type Compare func(a, b string) int 10 | 11 | // Tree is a red-black tree for key-value pairs where key is string. 12 | type Tree struct { 13 | root *node 14 | compare Compare 15 | } 16 | 17 | // Pair is a key-value pair representing tree node content. 18 | type Pair struct { 19 | Key string 20 | Value uint16 21 | } 22 | 23 | // NewTree creates empty tree with default comparison operation (strings.Compare). 24 | func NewTree() *Tree { 25 | return &Tree{compare: strings.Compare} 26 | } 27 | 28 | // NewTreeWithCustomComparison creates empty tree with given comparison operation. 29 | func NewTreeWithCustomComparison(compare Compare) *Tree { 30 | return &Tree{compare: compare} 31 | } 32 | 33 | // Insert puts given key-value pair to the tree and returns pointer to new root. 34 | func (t *Tree) Insert(key string, value uint16) *Tree { 35 | var ( 36 | n *node 37 | c Compare 38 | ) 39 | 40 | if t == nil { 41 | c = strings.Compare 42 | } else { 43 | n = t.root 44 | c = t.compare 45 | } 46 | 47 | return &Tree{root: n.insert(key, value, c), compare: c} 48 | } 49 | 50 | // InplaceInsert inserts or replaces given key-value pair in the tree. The method inserts data directly to current tree so make sure you have exclusive access to it. 51 | func (t *Tree) InplaceInsert(key string, value uint16) { 52 | t.root = t.root.inplaceInsert(key, value, t.compare) 53 | } 54 | 55 | // Get returns value by given key. 56 | func (t *Tree) Get(key string) (uint16, bool) { 57 | if t == nil { 58 | return 0, false 59 | } 60 | 61 | return t.root.get(key, t.compare) 62 | } 63 | 64 | // Enumerate returns channel which is populated by key pair values in order of keys. 65 | func (t *Tree) Enumerate() chan Pair { 66 | ch := make(chan Pair) 67 | 68 | go func() { 69 | defer close(ch) 70 | 71 | if t == nil { 72 | return 73 | } 74 | 75 | t.root.enumerate(ch) 76 | }() 77 | 78 | return ch 79 | } 80 | 81 | // Delete removes node by given key. It returns copy of tree and true if node has been indeed deleted otherwise original tree and false. 82 | func (t *Tree) Delete(key string) (*Tree, bool) { 83 | if t == nil { 84 | return nil, false 85 | } 86 | 87 | c := t.compare 88 | root, ok := t.root.del(key, c) 89 | return &Tree{root: root, compare: c}, ok 90 | } 91 | 92 | // IsEmpty returns true if given tree has no nodes. 93 | func (t *Tree) IsEmpty() bool { 94 | return t == nil || t.root == nil 95 | } 96 | 97 | // Dot dumps tree to Graphviz .dot format. 98 | func (t *Tree) Dot() string { 99 | body := "" 100 | 101 | if t != nil { 102 | body = t.root.dot() 103 | } 104 | 105 | return "digraph d {\n" + body + "}\n" 106 | } 107 | -------------------------------------------------------------------------------- /uintX/strtree32/strtree.go: -------------------------------------------------------------------------------- 1 | // Package strtree32 implements red-black tree for key value pairs with string keys, uint32 values and custom comparison. 2 | package strtree32 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint32 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import "strings" 7 | 8 | // Compare defines function interface for custom comparison. Function implementing the interface should return value less than zero if its first argument precedes second one, zero if both are equal and positive if the second precedes. 9 | type Compare func(a, b string) int 10 | 11 | // Tree is a red-black tree for key-value pairs where key is string. 12 | type Tree struct { 13 | root *node 14 | compare Compare 15 | } 16 | 17 | // Pair is a key-value pair representing tree node content. 18 | type Pair struct { 19 | Key string 20 | Value uint32 21 | } 22 | 23 | // NewTree creates empty tree with default comparison operation (strings.Compare). 24 | func NewTree() *Tree { 25 | return &Tree{compare: strings.Compare} 26 | } 27 | 28 | // NewTreeWithCustomComparison creates empty tree with given comparison operation. 29 | func NewTreeWithCustomComparison(compare Compare) *Tree { 30 | return &Tree{compare: compare} 31 | } 32 | 33 | // Insert puts given key-value pair to the tree and returns pointer to new root. 34 | func (t *Tree) Insert(key string, value uint32) *Tree { 35 | var ( 36 | n *node 37 | c Compare 38 | ) 39 | 40 | if t == nil { 41 | c = strings.Compare 42 | } else { 43 | n = t.root 44 | c = t.compare 45 | } 46 | 47 | return &Tree{root: n.insert(key, value, c), compare: c} 48 | } 49 | 50 | // InplaceInsert inserts or replaces given key-value pair in the tree. The method inserts data directly to current tree so make sure you have exclusive access to it. 51 | func (t *Tree) InplaceInsert(key string, value uint32) { 52 | t.root = t.root.inplaceInsert(key, value, t.compare) 53 | } 54 | 55 | // Get returns value by given key. 56 | func (t *Tree) Get(key string) (uint32, bool) { 57 | if t == nil { 58 | return 0, false 59 | } 60 | 61 | return t.root.get(key, t.compare) 62 | } 63 | 64 | // Enumerate returns channel which is populated by key pair values in order of keys. 65 | func (t *Tree) Enumerate() chan Pair { 66 | ch := make(chan Pair) 67 | 68 | go func() { 69 | defer close(ch) 70 | 71 | if t == nil { 72 | return 73 | } 74 | 75 | t.root.enumerate(ch) 76 | }() 77 | 78 | return ch 79 | } 80 | 81 | // Delete removes node by given key. It returns copy of tree and true if node has been indeed deleted otherwise original tree and false. 82 | func (t *Tree) Delete(key string) (*Tree, bool) { 83 | if t == nil { 84 | return nil, false 85 | } 86 | 87 | c := t.compare 88 | root, ok := t.root.del(key, c) 89 | return &Tree{root: root, compare: c}, ok 90 | } 91 | 92 | // IsEmpty returns true if given tree has no nodes. 93 | func (t *Tree) IsEmpty() bool { 94 | return t == nil || t.root == nil 95 | } 96 | 97 | // Dot dumps tree to Graphviz .dot format. 98 | func (t *Tree) Dot() string { 99 | body := "" 100 | 101 | if t != nil { 102 | body = t.root.dot() 103 | } 104 | 105 | return "digraph d {\n" + body + "}\n" 106 | } 107 | -------------------------------------------------------------------------------- /uintX/strtree64/strtree.go: -------------------------------------------------------------------------------- 1 | // Package strtree64 implements red-black tree for key value pairs with string keys, uint64 values and custom comparison. 2 | package strtree64 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint64 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import "strings" 7 | 8 | // Compare defines function interface for custom comparison. Function implementing the interface should return value less than zero if its first argument precedes second one, zero if both are equal and positive if the second precedes. 9 | type Compare func(a, b string) int 10 | 11 | // Tree is a red-black tree for key-value pairs where key is string. 12 | type Tree struct { 13 | root *node 14 | compare Compare 15 | } 16 | 17 | // Pair is a key-value pair representing tree node content. 18 | type Pair struct { 19 | Key string 20 | Value uint64 21 | } 22 | 23 | // NewTree creates empty tree with default comparison operation (strings.Compare). 24 | func NewTree() *Tree { 25 | return &Tree{compare: strings.Compare} 26 | } 27 | 28 | // NewTreeWithCustomComparison creates empty tree with given comparison operation. 29 | func NewTreeWithCustomComparison(compare Compare) *Tree { 30 | return &Tree{compare: compare} 31 | } 32 | 33 | // Insert puts given key-value pair to the tree and returns pointer to new root. 34 | func (t *Tree) Insert(key string, value uint64) *Tree { 35 | var ( 36 | n *node 37 | c Compare 38 | ) 39 | 40 | if t == nil { 41 | c = strings.Compare 42 | } else { 43 | n = t.root 44 | c = t.compare 45 | } 46 | 47 | return &Tree{root: n.insert(key, value, c), compare: c} 48 | } 49 | 50 | // InplaceInsert inserts or replaces given key-value pair in the tree. The method inserts data directly to current tree so make sure you have exclusive access to it. 51 | func (t *Tree) InplaceInsert(key string, value uint64) { 52 | t.root = t.root.inplaceInsert(key, value, t.compare) 53 | } 54 | 55 | // Get returns value by given key. 56 | func (t *Tree) Get(key string) (uint64, bool) { 57 | if t == nil { 58 | return 0, false 59 | } 60 | 61 | return t.root.get(key, t.compare) 62 | } 63 | 64 | // Enumerate returns channel which is populated by key pair values in order of keys. 65 | func (t *Tree) Enumerate() chan Pair { 66 | ch := make(chan Pair) 67 | 68 | go func() { 69 | defer close(ch) 70 | 71 | if t == nil { 72 | return 73 | } 74 | 75 | t.root.enumerate(ch) 76 | }() 77 | 78 | return ch 79 | } 80 | 81 | // Delete removes node by given key. It returns copy of tree and true if node has been indeed deleted otherwise original tree and false. 82 | func (t *Tree) Delete(key string) (*Tree, bool) { 83 | if t == nil { 84 | return nil, false 85 | } 86 | 87 | c := t.compare 88 | root, ok := t.root.del(key, c) 89 | return &Tree{root: root, compare: c}, ok 90 | } 91 | 92 | // IsEmpty returns true if given tree has no nodes. 93 | func (t *Tree) IsEmpty() bool { 94 | return t == nil || t.root == nil 95 | } 96 | 97 | // Dot dumps tree to Graphviz .dot format. 98 | func (t *Tree) Dot() string { 99 | body := "" 100 | 101 | if t != nil { 102 | body = t.root.dot() 103 | } 104 | 105 | return "digraph d {\n" + body + "}\n" 106 | } 107 | -------------------------------------------------------------------------------- /domain/name.go: -------------------------------------------------------------------------------- 1 | // Package domain provide functions to parse and handle domain names and labels. 2 | package domain 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | "reflect" 8 | ) 9 | 10 | var ( 11 | // ErrTooManyLabels is returned for domain name with more than 127 labels. 12 | ErrTooManyLabels = errors.New("too many labels") 13 | // ErrEmptyLabel indicates that domain name contains empty label. 14 | ErrEmptyLabel = errors.New("empty label") 15 | // ErrLabelTooLong is returned when one of domain labels has more than 63 characters. 16 | ErrLabelTooLong = errors.New("label too long") 17 | // ErrNameTooLong is returned when domain name has more than 255 characters. 18 | ErrNameTooLong = errors.New("name too long") 19 | // ErrInvalidEscape is returned for invalid escape sequence. 20 | ErrInvalidEscape = errors.New("invalid escape sequence") 21 | ) 22 | 23 | // Name is a structure which represents domain name. 24 | type Name struct { 25 | h string 26 | c string 27 | } 28 | 29 | const ( 30 | // MaxName is maximum number of bytes for whole domain name. 31 | MaxName = 255 32 | // MaxLabels is maximum number of labels domain name can consist of. 33 | MaxLabels = MaxName / 2 34 | // MaxLabel is maximim number of bytes for single label. 35 | MaxLabel = 63 36 | ) 37 | 38 | // MakeNameFromString creates a Name from human-readable domain name string. 39 | func MakeNameFromString(s string) (Name, error) { 40 | out := Name{h: s} 41 | 42 | if len(s) < 1 { 43 | return out, nil 44 | } 45 | 46 | if len(s) == 1 && s[0] == '.' { 47 | return out, nil 48 | } 49 | 50 | var offs [MaxLabels]int 51 | 52 | n, err := markLabels(s, offs[:]) 53 | if err != nil { 54 | return out, err 55 | } 56 | 57 | var ( 58 | label [MaxLabel + 1]byte 59 | name [MaxName]byte 60 | ) 61 | 62 | j := 0 63 | end := len(s) 64 | for i := n - 1; i >= 0; i-- { 65 | start := offs[i] 66 | 67 | n, err := getLabel(s[start:end], label[:]) 68 | if err != nil { 69 | return out, err 70 | } 71 | 72 | if copied := copy(name[j:], label[:n]); copied < n { 73 | return out, ErrNameTooLong 74 | } 75 | 76 | j += n 77 | 78 | end = start 79 | } 80 | 81 | out.c = string(name[:j]) 82 | 83 | return out, nil 84 | } 85 | 86 | var ( 87 | reflectStringType = reflect.TypeOf("") 88 | reflectNameType = reflect.TypeOf(Name{}) 89 | ) 90 | 91 | // MakeNameFromReflection extracts domain name from value. The value should wrap Name or *Name otherwise MakeNameFromReflection panics. 92 | func MakeNameFromReflection(v reflect.Value) Name { 93 | t := v.Type() 94 | if v.Kind() == reflect.Ptr { 95 | v = v.Elem() 96 | } 97 | 98 | switch v.Type() { 99 | case reflectStringType: 100 | s := v.String() 101 | n, err := MakeNameFromString(s) 102 | if err != nil { 103 | panic(fmt.Errorf("can't make %q from %q (%s): %s", reflectNameType, t, s, err)) 104 | } 105 | 106 | return n 107 | 108 | case reflectNameType: 109 | return Name{v.Field(0).String(), v.Field(1).String()} 110 | } 111 | 112 | panic(fmt.Errorf("can't make %q from %q", reflectNameType, t)) 113 | } 114 | 115 | // String method returns domain name in human-readable format. 116 | func (n Name) String() string { 117 | return n.h 118 | } 119 | 120 | // GetLabel returns label starting from given offset and offset of the next label. The method returns zero offset for the last label and -1 in case of error. 121 | func (n Name) GetLabel(off int) (string, int) { 122 | if off == 0 && len(n.c) == 0 { 123 | return "", 0 124 | } 125 | 126 | if off < 0 || off >= len(n.c) { 127 | return "", -1 128 | } 129 | 130 | size := int(n.c[off]) 131 | if size < 1 || size > 63 { 132 | return "", -1 133 | } 134 | 135 | start := off + 1 136 | end := start + size 137 | if end >= len(n.c) { 138 | return n.c[start:], 0 139 | } 140 | 141 | return n.c[start:end], end 142 | } 143 | 144 | // GetLabels iterate through name labels in reversed order. 145 | func (n Name) GetLabels(f func(string) error) error { 146 | off := 0 147 | for off < len(n.c) { 148 | off++ 149 | next := off + int(n.c[off-1]) 150 | 151 | if err := f(n.c[off:next]); err != nil { 152 | return err 153 | } 154 | 155 | off = next 156 | } 157 | 158 | return nil 159 | } 160 | -------------------------------------------------------------------------------- /dltree/dltree.go: -------------------------------------------------------------------------------- 1 | // Package dltree implements red-black tree for key value pairs with domain label keys. 2 | package dltree 3 | 4 | import "github.com/infobloxopen/go-trees/domain" 5 | 6 | // Tree is a red-black tree for key-value pairs where key is domain label. 7 | type Tree struct { 8 | root *node 9 | } 10 | 11 | // Pair is a key-value pair representing tree node content. 12 | type Pair struct { 13 | Key string 14 | Value interface{} 15 | } 16 | 17 | // NewTree creates empty tree. 18 | func NewTree() *Tree { 19 | return new(Tree) 20 | } 21 | 22 | // Insert puts given key-value pair to the tree and returns pointer to new root. 23 | func (t *Tree) Insert(key string, value interface{}) *Tree { 24 | var ( 25 | n *node 26 | ) 27 | 28 | if t != nil { 29 | n = t.root 30 | } 31 | 32 | dl, _ := domain.MakeLabel(key) 33 | return &Tree{root: n.insert(dl, value)} 34 | } 35 | 36 | // RawInsert puts given key-value pair to the tree and returns pointer to new root. Expects bindary domain label on input. 37 | func (t *Tree) RawInsert(key string, value interface{}) *Tree { 38 | var ( 39 | n *node 40 | ) 41 | 42 | if t != nil { 43 | n = t.root 44 | } 45 | 46 | return &Tree{root: n.insert(key, value)} 47 | } 48 | 49 | // InplaceInsert inserts or replaces given key-value pair in the tree. The method inserts data directly to current tree so make sure you have exclusive access to it. 50 | func (t *Tree) InplaceInsert(key string, value interface{}) { 51 | dl, _ := domain.MakeLabel(key) 52 | t.root = t.root.inplaceInsert(dl, value) 53 | } 54 | 55 | // RawInplaceInsert inserts or replaces given key-value pair in the tree. The method inserts data directly to current tree so make sure you have exclusive access to it. Expects bindary domain label on input. 56 | func (t *Tree) RawInplaceInsert(key string, value interface{}) { 57 | t.root = t.root.inplaceInsert(key, value) 58 | } 59 | 60 | // Get returns value by given key. 61 | func (t *Tree) Get(key string) (interface{}, bool) { 62 | if t == nil { 63 | return nil, false 64 | } 65 | 66 | dl, _ := domain.MakeLabel(key) 67 | return t.root.get(dl) 68 | } 69 | 70 | // RawGet returns value by given key. Expects bindary domain label on input. 71 | func (t *Tree) RawGet(key string) (interface{}, bool) { 72 | if t == nil { 73 | return nil, false 74 | } 75 | 76 | return t.root.get(key) 77 | } 78 | 79 | // Enumerate returns channel which is populated by key pair values in order of keys. 80 | func (t *Tree) Enumerate() chan Pair { 81 | ch := make(chan Pair) 82 | 83 | go func() { 84 | defer close(ch) 85 | 86 | if t == nil { 87 | return 88 | } 89 | 90 | t.root.enumerate(ch) 91 | }() 92 | 93 | return ch 94 | } 95 | 96 | // RawEnumerate returns channel which is populated by key pair values in order of keys. Returns binary domain labels. 97 | func (t *Tree) RawEnumerate() chan Pair { 98 | ch := make(chan Pair) 99 | 100 | go func() { 101 | defer close(ch) 102 | 103 | if t == nil { 104 | return 105 | } 106 | 107 | t.root.rawEnumerate(ch) 108 | }() 109 | 110 | return ch 111 | } 112 | 113 | // Delete removes node by given key. It returns copy of tree and true if node has been indeed deleted otherwise copy of tree and false. 114 | func (t *Tree) Delete(key string) (*Tree, bool) { 115 | if t == nil { 116 | return nil, false 117 | } 118 | 119 | dl, _ := domain.MakeLabel(key) 120 | root, ok := t.root.del(dl) 121 | return &Tree{root: root}, ok 122 | } 123 | 124 | // RawDelete removes node by given key. It returns copy of tree and true if node has been indeed deleted otherwise copy of tree and false. Expects bindary domain label on input. 125 | func (t *Tree) RawDelete(key string) (*Tree, bool) { 126 | if t == nil { 127 | return nil, false 128 | } 129 | 130 | root, ok := t.root.del(key) 131 | return &Tree{root: root}, ok 132 | } 133 | 134 | // IsEmpty returns true if given tree has no nodes. 135 | func (t *Tree) IsEmpty() bool { 136 | return t == nil || t.root == nil 137 | } 138 | 139 | // Dot dumps tree to Graphviz .dot format. 140 | func (t *Tree) Dot() string { 141 | body := "" 142 | 143 | if t != nil { 144 | body = t.root.dot() 145 | } 146 | 147 | return "digraph d {\n" + body + "}\n" 148 | } 149 | -------------------------------------------------------------------------------- /domain/label.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | const ( 9 | escRegular = iota 10 | escFirstChar 11 | escSecondDigit 12 | escThirdDigit 13 | ) 14 | 15 | // MakeLabel makes uppercase domain label from given human-readable representation. Ignores ending dot. 16 | func MakeLabel(s string) (string, error) { 17 | var label [MaxLabel + 1]byte 18 | 19 | n, err := getLabel(s, label[:]) 20 | if err != nil { 21 | return "", err 22 | } 23 | 24 | return string(label[1:n]), nil 25 | } 26 | 27 | // MakeHumanReadableLabel makes human-readable label by escaping according RFC-4343. 28 | func MakeHumanReadableLabel(s string) string { 29 | var label [4 * MaxLabel]byte 30 | 31 | j := 0 32 | for i := 0; i < len(s); i++ { 33 | c := s[i] 34 | if c == '.' || c == '\\' { 35 | if j >= len(label)-1 { 36 | return string(label[:j]) 37 | } 38 | 39 | label[j] = '\\' 40 | label[j+1] = c 41 | j += 2 42 | 43 | } else if c < '!' || c > '~' { 44 | if j >= len(label)-3 { 45 | return string(label[:j]) 46 | } 47 | 48 | label[j] = '\\' 49 | 50 | r := c % 10 51 | label[j+3] = r + '0' 52 | 53 | c /= 10 54 | r = c % 10 55 | label[j+2] = r + '0' 56 | 57 | c /= 10 58 | label[j+1] = c + '0' 59 | 60 | j += 4 61 | } else if c >= 'A' && c <= 'Z' { 62 | label[j] = c | 0x20 63 | j++ 64 | } else { 65 | if j >= len(label) { 66 | return string(label[:j]) 67 | } 68 | 69 | label[j] = c 70 | j++ 71 | } 72 | } 73 | 74 | return string(label[:j]) 75 | } 76 | 77 | func markLabels(s string, offs []int) (int, error) { 78 | n := 0 79 | start := 0 80 | esc := escRegular 81 | var code int 82 | for i := 0; i < len(s); i++ { 83 | c := s[i] 84 | switch esc { 85 | case escRegular: 86 | switch c { 87 | case '.': 88 | if start >= i { 89 | return 0, ErrEmptyLabel 90 | } 91 | 92 | if n >= len(offs) { 93 | return 0, ErrTooManyLabels 94 | } 95 | 96 | offs[n] = start 97 | n++ 98 | 99 | start = i + 1 100 | 101 | case '\\': 102 | esc = escFirstChar 103 | } 104 | 105 | case escFirstChar: 106 | if c < '0' || c > '9' { 107 | esc = escRegular 108 | } else { 109 | code = int(c-'0') * 100 110 | if code > math.MaxUint8 { 111 | return 0, ErrInvalidEscape 112 | } 113 | 114 | esc = escSecondDigit 115 | } 116 | 117 | case escSecondDigit: 118 | if c < '0' || c > '9' { 119 | return 0, ErrInvalidEscape 120 | } 121 | 122 | code += int(c-'0') * 10 123 | if code > math.MaxUint8 { 124 | return 0, ErrInvalidEscape 125 | } 126 | 127 | esc = escThirdDigit 128 | 129 | case escThirdDigit: 130 | if c < '0' || c > '9' { 131 | return 0, ErrInvalidEscape 132 | } 133 | 134 | code += int(c - '0') 135 | if code > math.MaxUint8 { 136 | return 0, ErrInvalidEscape 137 | } 138 | 139 | esc = escRegular 140 | } 141 | } 142 | 143 | if esc != escRegular { 144 | return 0, ErrInvalidEscape 145 | } 146 | 147 | if start < len(s) { 148 | if n >= len(offs) { 149 | return 0, ErrTooManyLabels 150 | } 151 | 152 | offs[n] = start 153 | n++ 154 | } 155 | 156 | return n, nil 157 | } 158 | 159 | func getLabel(s string, out []byte) (int, error) { 160 | j := 1 161 | esc := escRegular 162 | var code int 163 | 164 | Loop: 165 | for i := 0; i < len(s); i++ { 166 | c := s[i] 167 | switch esc { 168 | case escRegular: 169 | switch c { 170 | default: 171 | if c >= 'a' && c <= 'z' { 172 | c &= 0xdf 173 | } 174 | 175 | if j >= len(out) { 176 | return 0, ErrLabelTooLong 177 | } 178 | 179 | out[j] = c 180 | j++ 181 | 182 | case '.': 183 | if i < len(s)-1 { 184 | panic(fmt.Errorf("unescaped dot at %d index before last character %d", i, len(s)-1)) 185 | } 186 | 187 | break Loop 188 | 189 | case '\\': 190 | esc = escFirstChar 191 | } 192 | 193 | case escFirstChar: 194 | if c < '0' || c > '9' { 195 | if c >= 'a' && c <= 'z' { 196 | c &= 0xdf 197 | } 198 | 199 | if j >= len(out) { 200 | return 0, ErrLabelTooLong 201 | } 202 | 203 | out[j] = c 204 | j++ 205 | 206 | esc = escRegular 207 | } else { 208 | code = int(c-'0') * 100 209 | if code > math.MaxUint8 { 210 | return 0, ErrInvalidEscape 211 | } 212 | 213 | esc = escSecondDigit 214 | } 215 | 216 | case escSecondDigit: 217 | if c < '0' || c > '9' { 218 | return 0, ErrInvalidEscape 219 | } 220 | 221 | code += int(c-'0') * 10 222 | if code > math.MaxUint8 { 223 | return 0, ErrInvalidEscape 224 | } 225 | 226 | esc = escThirdDigit 227 | 228 | case escThirdDigit: 229 | if c < '0' || c > '9' { 230 | return 0, ErrInvalidEscape 231 | } 232 | 233 | code += int(c - '0') 234 | if code > math.MaxUint8 { 235 | return 0, ErrInvalidEscape 236 | } 237 | 238 | c = byte(code) 239 | if c >= 'a' && c <= 'z' { 240 | c &= 0xdf 241 | } 242 | 243 | if j >= len(out) { 244 | return 0, ErrLabelTooLong 245 | } 246 | 247 | out[j] = c 248 | j++ 249 | 250 | esc = escRegular 251 | } 252 | } 253 | 254 | if esc != escRegular { 255 | return 0, ErrInvalidEscape 256 | } 257 | 258 | out[0] = byte(j - 1) 259 | 260 | return j, nil 261 | } 262 | -------------------------------------------------------------------------------- /uintX/domaintree{{.bits}}/domaintree.{{.ext}}: -------------------------------------------------------------------------------- 1 | // Package domaintree{{.bits}} implements radix tree data structure for domain names. 2 | package domaintree{{.bits}} 3 | 4 | // {{.warning}} 5 | 6 | import ( 7 | "errors" 8 | 9 | "github.com/infobloxopen/go-trees/domain" 10 | ) 11 | 12 | // Node is a radix tree for domain names. 13 | type Node struct { 14 | branches *labelTree 15 | 16 | hasValue bool 17 | value uint{{.bits}} 18 | } 19 | 20 | // Pair represents a key-value pair returned by Enumerate method. 21 | type Pair struct { 22 | Key string 23 | Value uint{{.bits}} 24 | } 25 | 26 | var errStopIterations = errors.New("stop iterations") 27 | 28 | // Insert puts value using given domain as a key. The method returns new tree (old one remains unaffected). 29 | func (n *Node) Insert(d domain.Name, v uint{{.bits}}) *Node { 30 | n = n.copy() 31 | r := n 32 | 33 | d.GetLabels(func(label string) error { 34 | next, ok := n.branches.rawGet(label) 35 | if ok { 36 | next = next.copy() 37 | } else { 38 | next = new(Node) 39 | } 40 | 41 | n.branches = n.branches.rawInsert(label, next) 42 | n = next 43 | 44 | return nil 45 | }) 46 | 47 | n.hasValue = true 48 | n.value = v 49 | 50 | return r 51 | } 52 | 53 | // InplaceInsert puts or replaces value using given domain as a key. The method inserts data directly to current tree so make sure you have exclusive access to it. 54 | func (n *Node) InplaceInsert(d domain.Name, v uint{{.bits}}) { 55 | if n.branches == nil { 56 | n.branches = newLabelTree() 57 | } 58 | 59 | d.GetLabels(func(label string) error { 60 | next, ok := n.branches.rawGet(label) 61 | if ok { 62 | n = next 63 | } else { 64 | next := &Node{branches: newLabelTree()} 65 | n.branches.rawInplaceInsert(label, next) 66 | n = next 67 | } 68 | 69 | return nil 70 | }) 71 | 72 | n.hasValue = true 73 | n.value = v 74 | } 75 | 76 | // Enumerate returns key-value pairs in given tree. It lists domains in the same order for the same tree. 77 | func (n *Node) Enumerate() chan Pair { 78 | ch := make(chan Pair) 79 | 80 | go func() { 81 | defer close(ch) 82 | n.enumerate("", ch) 83 | }() 84 | 85 | return ch 86 | } 87 | 88 | // Get gets value for domain which is equal to domain in the tree or is a subdomain of existing domain. 89 | func (n *Node) Get(d domain.Name) (uint{{.bits}}, bool) { 90 | if n == nil { 91 | return 0, false 92 | } 93 | 94 | var value uint{{.bits}} 95 | hasValue := false 96 | 97 | d.GetLabels(func(label string) error { 98 | next, ok := n.branches.rawGet(label) 99 | if !ok { 100 | return errStopIterations 101 | } 102 | 103 | n = next 104 | if n.hasValue { 105 | value = n.value 106 | hasValue = true 107 | } 108 | return nil 109 | }) 110 | 111 | return value, hasValue 112 | } 113 | 114 | // DeleteSubdomains removes current domain and all its subdomains if any. It returns new tree and flag if deletion indeed occurs. 115 | func (n *Node) DeleteSubdomains(d domain.Name) (*Node, bool) { 116 | if n == nil { 117 | return nil, false 118 | } 119 | 120 | var ( 121 | labels [domain.MaxLabels]string 122 | nodes [domain.MaxLabels]*Node 123 | ) 124 | 125 | i := n.getBranch(d, labels[:], nodes[:]) 126 | if i >= len(nodes) || !nodes[i].hasValue && n.branches.isEmpty() { 127 | return n, false 128 | } 129 | 130 | i++ 131 | if i >= len(nodes) { 132 | return new(Node), true 133 | } 134 | 135 | n = nodes[i].copy() 136 | n.branches, _ = n.branches.rawDel(labels[i]) 137 | i++ 138 | 139 | return n.copyBranch(labels[i:], nodes[i:]), true 140 | } 141 | 142 | // Delete removes current domain only. It returns new tree and flag if deletion indeed occurs. 143 | func (n *Node) Delete(d domain.Name) (*Node, bool) { 144 | if n == nil { 145 | return nil, false 146 | } 147 | 148 | var ( 149 | labels [domain.MaxLabels]string 150 | nodes [domain.MaxLabels]*Node 151 | ) 152 | 153 | i := n.getBranch(d, labels[:], nodes[:]) 154 | if i >= len(nodes) || !nodes[i].hasValue { 155 | return n, false 156 | } 157 | 158 | n = nodes[i] 159 | i++ 160 | 161 | branches := n.branches 162 | if i >= len(nodes) { 163 | if branches.isEmpty() { 164 | return new(Node), true 165 | } 166 | 167 | return &Node{branches: branches}, true 168 | } 169 | 170 | n = nodes[i].copy() 171 | if branches.isEmpty() { 172 | n.branches, _ = n.branches.rawDel(labels[i]) 173 | } else { 174 | n.branches = n.branches.rawInsert(labels[i], &Node{branches: branches}) 175 | } 176 | i++ 177 | 178 | return n.copyBranch(labels[i:], nodes[i:]), true 179 | } 180 | 181 | func (n *Node) enumerate(s string, ch chan Pair) { 182 | if n == nil { 183 | return 184 | } 185 | 186 | if n.hasValue { 187 | ch <- Pair{ 188 | Key: s, 189 | Value: n.value} 190 | } 191 | 192 | for item := range n.branches.enumerate() { 193 | sub := item.Key 194 | if len(s) > 0 { 195 | sub += "." + s 196 | } 197 | 198 | item.Value.enumerate(sub, ch) 199 | } 200 | } 201 | 202 | func (n *Node) copy() *Node { 203 | if n == nil { 204 | return new(Node) 205 | } 206 | 207 | return &Node{ 208 | branches: n.branches, 209 | hasValue: n.hasValue, 210 | value: n.value, 211 | } 212 | } 213 | 214 | func (n *Node) getBranch(d domain.Name, labels []string, nodes []*Node) int { 215 | i := len(labels) - 1 216 | nodes[i] = n 217 | 218 | if err := d.GetLabels(func(label string) error { 219 | labels[i] = label 220 | 221 | next, ok := n.branches.rawGet(label) 222 | if !ok { 223 | return errStopIterations 224 | } 225 | 226 | n = next 227 | 228 | i-- 229 | nodes[i] = n 230 | return nil 231 | }); err != nil { 232 | return len(labels) 233 | } 234 | 235 | return i 236 | } 237 | 238 | func (n *Node) copyBranch(labels []string, nodes []*Node) *Node { 239 | for i, p := range nodes { 240 | p = p.copy() 241 | if !n.hasValue && n.branches.isEmpty() { 242 | p.branches, _ = p.branches.rawDel(labels[i]) 243 | } else { 244 | p.branches = p.branches.rawInsert(labels[i], n) 245 | } 246 | 247 | n = p 248 | } 249 | 250 | return n 251 | } 252 | -------------------------------------------------------------------------------- /uintX/domaintree8/domaintree.go: -------------------------------------------------------------------------------- 1 | // Package domaintree8 implements radix tree data structure for domain names. 2 | package domaintree8 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint8 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import ( 7 | "errors" 8 | 9 | "github.com/infobloxopen/go-trees/domain" 10 | ) 11 | 12 | // Node is a radix tree for domain names. 13 | type Node struct { 14 | branches *labelTree 15 | 16 | hasValue bool 17 | value uint8 18 | } 19 | 20 | // Pair represents a key-value pair returned by Enumerate method. 21 | type Pair struct { 22 | Key string 23 | Value uint8 24 | } 25 | 26 | var errStopIterations = errors.New("stop iterations") 27 | 28 | // Insert puts value using given domain as a key. The method returns new tree (old one remains unaffected). 29 | func (n *Node) Insert(d domain.Name, v uint8) *Node { 30 | n = n.copy() 31 | r := n 32 | 33 | d.GetLabels(func(label string) error { 34 | next, ok := n.branches.rawGet(label) 35 | if ok { 36 | next = next.copy() 37 | } else { 38 | next = new(Node) 39 | } 40 | 41 | n.branches = n.branches.rawInsert(label, next) 42 | n = next 43 | 44 | return nil 45 | }) 46 | 47 | n.hasValue = true 48 | n.value = v 49 | 50 | return r 51 | } 52 | 53 | // InplaceInsert puts or replaces value using given domain as a key. The method inserts data directly to current tree so make sure you have exclusive access to it. 54 | func (n *Node) InplaceInsert(d domain.Name, v uint8) { 55 | if n.branches == nil { 56 | n.branches = newLabelTree() 57 | } 58 | 59 | d.GetLabels(func(label string) error { 60 | next, ok := n.branches.rawGet(label) 61 | if ok { 62 | n = next 63 | } else { 64 | next := &Node{branches: newLabelTree()} 65 | n.branches.rawInplaceInsert(label, next) 66 | n = next 67 | } 68 | 69 | return nil 70 | }) 71 | 72 | n.hasValue = true 73 | n.value = v 74 | } 75 | 76 | // Enumerate returns key-value pairs in given tree. It lists domains in the same order for the same tree. 77 | func (n *Node) Enumerate() chan Pair { 78 | ch := make(chan Pair) 79 | 80 | go func() { 81 | defer close(ch) 82 | n.enumerate("", ch) 83 | }() 84 | 85 | return ch 86 | } 87 | 88 | // Get gets value for domain which is equal to domain in the tree or is a subdomain of existing domain. 89 | func (n *Node) Get(d domain.Name) (uint8, bool) { 90 | if n == nil { 91 | return 0, false 92 | } 93 | 94 | var value uint8 95 | hasValue := false 96 | 97 | d.GetLabels(func(label string) error { 98 | next, ok := n.branches.rawGet(label) 99 | if !ok { 100 | return errStopIterations 101 | } 102 | 103 | n = next 104 | if n.hasValue { 105 | value = n.value 106 | hasValue = true 107 | } 108 | return nil 109 | }) 110 | 111 | return value, hasValue 112 | } 113 | 114 | // DeleteSubdomains removes current domain and all its subdomains if any. It returns new tree and flag if deletion indeed occurs. 115 | func (n *Node) DeleteSubdomains(d domain.Name) (*Node, bool) { 116 | if n == nil { 117 | return nil, false 118 | } 119 | 120 | var ( 121 | labels [domain.MaxLabels]string 122 | nodes [domain.MaxLabels]*Node 123 | ) 124 | 125 | i := n.getBranch(d, labels[:], nodes[:]) 126 | if i >= len(nodes) || !nodes[i].hasValue && n.branches.isEmpty() { 127 | return n, false 128 | } 129 | 130 | i++ 131 | if i >= len(nodes) { 132 | return new(Node), true 133 | } 134 | 135 | n = nodes[i].copy() 136 | n.branches, _ = n.branches.rawDel(labels[i]) 137 | i++ 138 | 139 | return n.copyBranch(labels[i:], nodes[i:]), true 140 | } 141 | 142 | // Delete removes current domain only. It returns new tree and flag if deletion indeed occurs. 143 | func (n *Node) Delete(d domain.Name) (*Node, bool) { 144 | if n == nil { 145 | return nil, false 146 | } 147 | 148 | var ( 149 | labels [domain.MaxLabels]string 150 | nodes [domain.MaxLabels]*Node 151 | ) 152 | 153 | i := n.getBranch(d, labels[:], nodes[:]) 154 | if i >= len(nodes) || !nodes[i].hasValue { 155 | return n, false 156 | } 157 | 158 | n = nodes[i] 159 | i++ 160 | 161 | branches := n.branches 162 | if i >= len(nodes) { 163 | if branches.isEmpty() { 164 | return new(Node), true 165 | } 166 | 167 | return &Node{branches: branches}, true 168 | } 169 | 170 | n = nodes[i].copy() 171 | if branches.isEmpty() { 172 | n.branches, _ = n.branches.rawDel(labels[i]) 173 | } else { 174 | n.branches = n.branches.rawInsert(labels[i], &Node{branches: branches}) 175 | } 176 | i++ 177 | 178 | return n.copyBranch(labels[i:], nodes[i:]), true 179 | } 180 | 181 | func (n *Node) enumerate(s string, ch chan Pair) { 182 | if n == nil { 183 | return 184 | } 185 | 186 | if n.hasValue { 187 | ch <- Pair{ 188 | Key: s, 189 | Value: n.value} 190 | } 191 | 192 | for item := range n.branches.enumerate() { 193 | sub := item.Key 194 | if len(s) > 0 { 195 | sub += "." + s 196 | } 197 | 198 | item.Value.enumerate(sub, ch) 199 | } 200 | } 201 | 202 | func (n *Node) copy() *Node { 203 | if n == nil { 204 | return new(Node) 205 | } 206 | 207 | return &Node{ 208 | branches: n.branches, 209 | hasValue: n.hasValue, 210 | value: n.value, 211 | } 212 | } 213 | 214 | func (n *Node) getBranch(d domain.Name, labels []string, nodes []*Node) int { 215 | i := len(labels) - 1 216 | nodes[i] = n 217 | 218 | if err := d.GetLabels(func(label string) error { 219 | labels[i] = label 220 | 221 | next, ok := n.branches.rawGet(label) 222 | if !ok { 223 | return errStopIterations 224 | } 225 | 226 | n = next 227 | 228 | i-- 229 | nodes[i] = n 230 | return nil 231 | }); err != nil { 232 | return len(labels) 233 | } 234 | 235 | return i 236 | } 237 | 238 | func (n *Node) copyBranch(labels []string, nodes []*Node) *Node { 239 | for i, p := range nodes { 240 | p = p.copy() 241 | if !n.hasValue && n.branches.isEmpty() { 242 | p.branches, _ = p.branches.rawDel(labels[i]) 243 | } else { 244 | p.branches = p.branches.rawInsert(labels[i], n) 245 | } 246 | 247 | n = p 248 | } 249 | 250 | return n 251 | } 252 | -------------------------------------------------------------------------------- /uintX/domaintree16/domaintree.go: -------------------------------------------------------------------------------- 1 | // Package domaintree16 implements radix tree data structure for domain names. 2 | package domaintree16 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint16 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import ( 7 | "errors" 8 | 9 | "github.com/infobloxopen/go-trees/domain" 10 | ) 11 | 12 | // Node is a radix tree for domain names. 13 | type Node struct { 14 | branches *labelTree 15 | 16 | hasValue bool 17 | value uint16 18 | } 19 | 20 | // Pair represents a key-value pair returned by Enumerate method. 21 | type Pair struct { 22 | Key string 23 | Value uint16 24 | } 25 | 26 | var errStopIterations = errors.New("stop iterations") 27 | 28 | // Insert puts value using given domain as a key. The method returns new tree (old one remains unaffected). 29 | func (n *Node) Insert(d domain.Name, v uint16) *Node { 30 | n = n.copy() 31 | r := n 32 | 33 | d.GetLabels(func(label string) error { 34 | next, ok := n.branches.rawGet(label) 35 | if ok { 36 | next = next.copy() 37 | } else { 38 | next = new(Node) 39 | } 40 | 41 | n.branches = n.branches.rawInsert(label, next) 42 | n = next 43 | 44 | return nil 45 | }) 46 | 47 | n.hasValue = true 48 | n.value = v 49 | 50 | return r 51 | } 52 | 53 | // InplaceInsert puts or replaces value using given domain as a key. The method inserts data directly to current tree so make sure you have exclusive access to it. 54 | func (n *Node) InplaceInsert(d domain.Name, v uint16) { 55 | if n.branches == nil { 56 | n.branches = newLabelTree() 57 | } 58 | 59 | d.GetLabels(func(label string) error { 60 | next, ok := n.branches.rawGet(label) 61 | if ok { 62 | n = next 63 | } else { 64 | next := &Node{branches: newLabelTree()} 65 | n.branches.rawInplaceInsert(label, next) 66 | n = next 67 | } 68 | 69 | return nil 70 | }) 71 | 72 | n.hasValue = true 73 | n.value = v 74 | } 75 | 76 | // Enumerate returns key-value pairs in given tree. It lists domains in the same order for the same tree. 77 | func (n *Node) Enumerate() chan Pair { 78 | ch := make(chan Pair) 79 | 80 | go func() { 81 | defer close(ch) 82 | n.enumerate("", ch) 83 | }() 84 | 85 | return ch 86 | } 87 | 88 | // Get gets value for domain which is equal to domain in the tree or is a subdomain of existing domain. 89 | func (n *Node) Get(d domain.Name) (uint16, bool) { 90 | if n == nil { 91 | return 0, false 92 | } 93 | 94 | var value uint16 95 | hasValue := false 96 | 97 | d.GetLabels(func(label string) error { 98 | next, ok := n.branches.rawGet(label) 99 | if !ok { 100 | return errStopIterations 101 | } 102 | 103 | n = next 104 | if n.hasValue { 105 | value = n.value 106 | hasValue = true 107 | } 108 | return nil 109 | }) 110 | 111 | return value, hasValue 112 | } 113 | 114 | // DeleteSubdomains removes current domain and all its subdomains if any. It returns new tree and flag if deletion indeed occurs. 115 | func (n *Node) DeleteSubdomains(d domain.Name) (*Node, bool) { 116 | if n == nil { 117 | return nil, false 118 | } 119 | 120 | var ( 121 | labels [domain.MaxLabels]string 122 | nodes [domain.MaxLabels]*Node 123 | ) 124 | 125 | i := n.getBranch(d, labels[:], nodes[:]) 126 | if i >= len(nodes) || !nodes[i].hasValue && n.branches.isEmpty() { 127 | return n, false 128 | } 129 | 130 | i++ 131 | if i >= len(nodes) { 132 | return new(Node), true 133 | } 134 | 135 | n = nodes[i].copy() 136 | n.branches, _ = n.branches.rawDel(labels[i]) 137 | i++ 138 | 139 | return n.copyBranch(labels[i:], nodes[i:]), true 140 | } 141 | 142 | // Delete removes current domain only. It returns new tree and flag if deletion indeed occurs. 143 | func (n *Node) Delete(d domain.Name) (*Node, bool) { 144 | if n == nil { 145 | return nil, false 146 | } 147 | 148 | var ( 149 | labels [domain.MaxLabels]string 150 | nodes [domain.MaxLabels]*Node 151 | ) 152 | 153 | i := n.getBranch(d, labels[:], nodes[:]) 154 | if i >= len(nodes) || !nodes[i].hasValue { 155 | return n, false 156 | } 157 | 158 | n = nodes[i] 159 | i++ 160 | 161 | branches := n.branches 162 | if i >= len(nodes) { 163 | if branches.isEmpty() { 164 | return new(Node), true 165 | } 166 | 167 | return &Node{branches: branches}, true 168 | } 169 | 170 | n = nodes[i].copy() 171 | if branches.isEmpty() { 172 | n.branches, _ = n.branches.rawDel(labels[i]) 173 | } else { 174 | n.branches = n.branches.rawInsert(labels[i], &Node{branches: branches}) 175 | } 176 | i++ 177 | 178 | return n.copyBranch(labels[i:], nodes[i:]), true 179 | } 180 | 181 | func (n *Node) enumerate(s string, ch chan Pair) { 182 | if n == nil { 183 | return 184 | } 185 | 186 | if n.hasValue { 187 | ch <- Pair{ 188 | Key: s, 189 | Value: n.value} 190 | } 191 | 192 | for item := range n.branches.enumerate() { 193 | sub := item.Key 194 | if len(s) > 0 { 195 | sub += "." + s 196 | } 197 | 198 | item.Value.enumerate(sub, ch) 199 | } 200 | } 201 | 202 | func (n *Node) copy() *Node { 203 | if n == nil { 204 | return new(Node) 205 | } 206 | 207 | return &Node{ 208 | branches: n.branches, 209 | hasValue: n.hasValue, 210 | value: n.value, 211 | } 212 | } 213 | 214 | func (n *Node) getBranch(d domain.Name, labels []string, nodes []*Node) int { 215 | i := len(labels) - 1 216 | nodes[i] = n 217 | 218 | if err := d.GetLabels(func(label string) error { 219 | labels[i] = label 220 | 221 | next, ok := n.branches.rawGet(label) 222 | if !ok { 223 | return errStopIterations 224 | } 225 | 226 | n = next 227 | 228 | i-- 229 | nodes[i] = n 230 | return nil 231 | }); err != nil { 232 | return len(labels) 233 | } 234 | 235 | return i 236 | } 237 | 238 | func (n *Node) copyBranch(labels []string, nodes []*Node) *Node { 239 | for i, p := range nodes { 240 | p = p.copy() 241 | if !n.hasValue && n.branches.isEmpty() { 242 | p.branches, _ = p.branches.rawDel(labels[i]) 243 | } else { 244 | p.branches = p.branches.rawInsert(labels[i], n) 245 | } 246 | 247 | n = p 248 | } 249 | 250 | return n 251 | } 252 | -------------------------------------------------------------------------------- /uintX/domaintree32/domaintree.go: -------------------------------------------------------------------------------- 1 | // Package domaintree32 implements radix tree data structure for domain names. 2 | package domaintree32 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint32 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import ( 7 | "errors" 8 | 9 | "github.com/infobloxopen/go-trees/domain" 10 | ) 11 | 12 | // Node is a radix tree for domain names. 13 | type Node struct { 14 | branches *labelTree 15 | 16 | hasValue bool 17 | value uint32 18 | } 19 | 20 | // Pair represents a key-value pair returned by Enumerate method. 21 | type Pair struct { 22 | Key string 23 | Value uint32 24 | } 25 | 26 | var errStopIterations = errors.New("stop iterations") 27 | 28 | // Insert puts value using given domain as a key. The method returns new tree (old one remains unaffected). 29 | func (n *Node) Insert(d domain.Name, v uint32) *Node { 30 | n = n.copy() 31 | r := n 32 | 33 | d.GetLabels(func(label string) error { 34 | next, ok := n.branches.rawGet(label) 35 | if ok { 36 | next = next.copy() 37 | } else { 38 | next = new(Node) 39 | } 40 | 41 | n.branches = n.branches.rawInsert(label, next) 42 | n = next 43 | 44 | return nil 45 | }) 46 | 47 | n.hasValue = true 48 | n.value = v 49 | 50 | return r 51 | } 52 | 53 | // InplaceInsert puts or replaces value using given domain as a key. The method inserts data directly to current tree so make sure you have exclusive access to it. 54 | func (n *Node) InplaceInsert(d domain.Name, v uint32) { 55 | if n.branches == nil { 56 | n.branches = newLabelTree() 57 | } 58 | 59 | d.GetLabels(func(label string) error { 60 | next, ok := n.branches.rawGet(label) 61 | if ok { 62 | n = next 63 | } else { 64 | next := &Node{branches: newLabelTree()} 65 | n.branches.rawInplaceInsert(label, next) 66 | n = next 67 | } 68 | 69 | return nil 70 | }) 71 | 72 | n.hasValue = true 73 | n.value = v 74 | } 75 | 76 | // Enumerate returns key-value pairs in given tree. It lists domains in the same order for the same tree. 77 | func (n *Node) Enumerate() chan Pair { 78 | ch := make(chan Pair) 79 | 80 | go func() { 81 | defer close(ch) 82 | n.enumerate("", ch) 83 | }() 84 | 85 | return ch 86 | } 87 | 88 | // Get gets value for domain which is equal to domain in the tree or is a subdomain of existing domain. 89 | func (n *Node) Get(d domain.Name) (uint32, bool) { 90 | if n == nil { 91 | return 0, false 92 | } 93 | 94 | var value uint32 95 | hasValue := false 96 | 97 | d.GetLabels(func(label string) error { 98 | next, ok := n.branches.rawGet(label) 99 | if !ok { 100 | return errStopIterations 101 | } 102 | 103 | n = next 104 | if n.hasValue { 105 | value = n.value 106 | hasValue = true 107 | } 108 | return nil 109 | }) 110 | 111 | return value, hasValue 112 | } 113 | 114 | // DeleteSubdomains removes current domain and all its subdomains if any. It returns new tree and flag if deletion indeed occurs. 115 | func (n *Node) DeleteSubdomains(d domain.Name) (*Node, bool) { 116 | if n == nil { 117 | return nil, false 118 | } 119 | 120 | var ( 121 | labels [domain.MaxLabels]string 122 | nodes [domain.MaxLabels]*Node 123 | ) 124 | 125 | i := n.getBranch(d, labels[:], nodes[:]) 126 | if i >= len(nodes) || !nodes[i].hasValue && n.branches.isEmpty() { 127 | return n, false 128 | } 129 | 130 | i++ 131 | if i >= len(nodes) { 132 | return new(Node), true 133 | } 134 | 135 | n = nodes[i].copy() 136 | n.branches, _ = n.branches.rawDel(labels[i]) 137 | i++ 138 | 139 | return n.copyBranch(labels[i:], nodes[i:]), true 140 | } 141 | 142 | // Delete removes current domain only. It returns new tree and flag if deletion indeed occurs. 143 | func (n *Node) Delete(d domain.Name) (*Node, bool) { 144 | if n == nil { 145 | return nil, false 146 | } 147 | 148 | var ( 149 | labels [domain.MaxLabels]string 150 | nodes [domain.MaxLabels]*Node 151 | ) 152 | 153 | i := n.getBranch(d, labels[:], nodes[:]) 154 | if i >= len(nodes) || !nodes[i].hasValue { 155 | return n, false 156 | } 157 | 158 | n = nodes[i] 159 | i++ 160 | 161 | branches := n.branches 162 | if i >= len(nodes) { 163 | if branches.isEmpty() { 164 | return new(Node), true 165 | } 166 | 167 | return &Node{branches: branches}, true 168 | } 169 | 170 | n = nodes[i].copy() 171 | if branches.isEmpty() { 172 | n.branches, _ = n.branches.rawDel(labels[i]) 173 | } else { 174 | n.branches = n.branches.rawInsert(labels[i], &Node{branches: branches}) 175 | } 176 | i++ 177 | 178 | return n.copyBranch(labels[i:], nodes[i:]), true 179 | } 180 | 181 | func (n *Node) enumerate(s string, ch chan Pair) { 182 | if n == nil { 183 | return 184 | } 185 | 186 | if n.hasValue { 187 | ch <- Pair{ 188 | Key: s, 189 | Value: n.value} 190 | } 191 | 192 | for item := range n.branches.enumerate() { 193 | sub := item.Key 194 | if len(s) > 0 { 195 | sub += "." + s 196 | } 197 | 198 | item.Value.enumerate(sub, ch) 199 | } 200 | } 201 | 202 | func (n *Node) copy() *Node { 203 | if n == nil { 204 | return new(Node) 205 | } 206 | 207 | return &Node{ 208 | branches: n.branches, 209 | hasValue: n.hasValue, 210 | value: n.value, 211 | } 212 | } 213 | 214 | func (n *Node) getBranch(d domain.Name, labels []string, nodes []*Node) int { 215 | i := len(labels) - 1 216 | nodes[i] = n 217 | 218 | if err := d.GetLabels(func(label string) error { 219 | labels[i] = label 220 | 221 | next, ok := n.branches.rawGet(label) 222 | if !ok { 223 | return errStopIterations 224 | } 225 | 226 | n = next 227 | 228 | i-- 229 | nodes[i] = n 230 | return nil 231 | }); err != nil { 232 | return len(labels) 233 | } 234 | 235 | return i 236 | } 237 | 238 | func (n *Node) copyBranch(labels []string, nodes []*Node) *Node { 239 | for i, p := range nodes { 240 | p = p.copy() 241 | if !n.hasValue && n.branches.isEmpty() { 242 | p.branches, _ = p.branches.rawDel(labels[i]) 243 | } else { 244 | p.branches = p.branches.rawInsert(labels[i], n) 245 | } 246 | 247 | n = p 248 | } 249 | 250 | return n 251 | } 252 | -------------------------------------------------------------------------------- /uintX/domaintree64/domaintree.go: -------------------------------------------------------------------------------- 1 | // Package domaintree64 implements radix tree data structure for domain names. 2 | package domaintree64 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint64 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import ( 7 | "errors" 8 | 9 | "github.com/infobloxopen/go-trees/domain" 10 | ) 11 | 12 | // Node is a radix tree for domain names. 13 | type Node struct { 14 | branches *labelTree 15 | 16 | hasValue bool 17 | value uint64 18 | } 19 | 20 | // Pair represents a key-value pair returned by Enumerate method. 21 | type Pair struct { 22 | Key string 23 | Value uint64 24 | } 25 | 26 | var errStopIterations = errors.New("stop iterations") 27 | 28 | // Insert puts value using given domain as a key. The method returns new tree (old one remains unaffected). 29 | func (n *Node) Insert(d domain.Name, v uint64) *Node { 30 | n = n.copy() 31 | r := n 32 | 33 | d.GetLabels(func(label string) error { 34 | next, ok := n.branches.rawGet(label) 35 | if ok { 36 | next = next.copy() 37 | } else { 38 | next = new(Node) 39 | } 40 | 41 | n.branches = n.branches.rawInsert(label, next) 42 | n = next 43 | 44 | return nil 45 | }) 46 | 47 | n.hasValue = true 48 | n.value = v 49 | 50 | return r 51 | } 52 | 53 | // InplaceInsert puts or replaces value using given domain as a key. The method inserts data directly to current tree so make sure you have exclusive access to it. 54 | func (n *Node) InplaceInsert(d domain.Name, v uint64) { 55 | if n.branches == nil { 56 | n.branches = newLabelTree() 57 | } 58 | 59 | d.GetLabels(func(label string) error { 60 | next, ok := n.branches.rawGet(label) 61 | if ok { 62 | n = next 63 | } else { 64 | next := &Node{branches: newLabelTree()} 65 | n.branches.rawInplaceInsert(label, next) 66 | n = next 67 | } 68 | 69 | return nil 70 | }) 71 | 72 | n.hasValue = true 73 | n.value = v 74 | } 75 | 76 | // Enumerate returns key-value pairs in given tree. It lists domains in the same order for the same tree. 77 | func (n *Node) Enumerate() chan Pair { 78 | ch := make(chan Pair) 79 | 80 | go func() { 81 | defer close(ch) 82 | n.enumerate("", ch) 83 | }() 84 | 85 | return ch 86 | } 87 | 88 | // Get gets value for domain which is equal to domain in the tree or is a subdomain of existing domain. 89 | func (n *Node) Get(d domain.Name) (uint64, bool) { 90 | if n == nil { 91 | return 0, false 92 | } 93 | 94 | var value uint64 95 | hasValue := false 96 | 97 | d.GetLabels(func(label string) error { 98 | next, ok := n.branches.rawGet(label) 99 | if !ok { 100 | return errStopIterations 101 | } 102 | 103 | n = next 104 | if n.hasValue { 105 | value = n.value 106 | hasValue = true 107 | } 108 | return nil 109 | }) 110 | 111 | return value, hasValue 112 | } 113 | 114 | // DeleteSubdomains removes current domain and all its subdomains if any. It returns new tree and flag if deletion indeed occurs. 115 | func (n *Node) DeleteSubdomains(d domain.Name) (*Node, bool) { 116 | if n == nil { 117 | return nil, false 118 | } 119 | 120 | var ( 121 | labels [domain.MaxLabels]string 122 | nodes [domain.MaxLabels]*Node 123 | ) 124 | 125 | i := n.getBranch(d, labels[:], nodes[:]) 126 | if i >= len(nodes) || !nodes[i].hasValue && n.branches.isEmpty() { 127 | return n, false 128 | } 129 | 130 | i++ 131 | if i >= len(nodes) { 132 | return new(Node), true 133 | } 134 | 135 | n = nodes[i].copy() 136 | n.branches, _ = n.branches.rawDel(labels[i]) 137 | i++ 138 | 139 | return n.copyBranch(labels[i:], nodes[i:]), true 140 | } 141 | 142 | // Delete removes current domain only. It returns new tree and flag if deletion indeed occurs. 143 | func (n *Node) Delete(d domain.Name) (*Node, bool) { 144 | if n == nil { 145 | return nil, false 146 | } 147 | 148 | var ( 149 | labels [domain.MaxLabels]string 150 | nodes [domain.MaxLabels]*Node 151 | ) 152 | 153 | i := n.getBranch(d, labels[:], nodes[:]) 154 | if i >= len(nodes) || !nodes[i].hasValue { 155 | return n, false 156 | } 157 | 158 | n = nodes[i] 159 | i++ 160 | 161 | branches := n.branches 162 | if i >= len(nodes) { 163 | if branches.isEmpty() { 164 | return new(Node), true 165 | } 166 | 167 | return &Node{branches: branches}, true 168 | } 169 | 170 | n = nodes[i].copy() 171 | if branches.isEmpty() { 172 | n.branches, _ = n.branches.rawDel(labels[i]) 173 | } else { 174 | n.branches = n.branches.rawInsert(labels[i], &Node{branches: branches}) 175 | } 176 | i++ 177 | 178 | return n.copyBranch(labels[i:], nodes[i:]), true 179 | } 180 | 181 | func (n *Node) enumerate(s string, ch chan Pair) { 182 | if n == nil { 183 | return 184 | } 185 | 186 | if n.hasValue { 187 | ch <- Pair{ 188 | Key: s, 189 | Value: n.value} 190 | } 191 | 192 | for item := range n.branches.enumerate() { 193 | sub := item.Key 194 | if len(s) > 0 { 195 | sub += "." + s 196 | } 197 | 198 | item.Value.enumerate(sub, ch) 199 | } 200 | } 201 | 202 | func (n *Node) copy() *Node { 203 | if n == nil { 204 | return new(Node) 205 | } 206 | 207 | return &Node{ 208 | branches: n.branches, 209 | hasValue: n.hasValue, 210 | value: n.value, 211 | } 212 | } 213 | 214 | func (n *Node) getBranch(d domain.Name, labels []string, nodes []*Node) int { 215 | i := len(labels) - 1 216 | nodes[i] = n 217 | 218 | if err := d.GetLabels(func(label string) error { 219 | labels[i] = label 220 | 221 | next, ok := n.branches.rawGet(label) 222 | if !ok { 223 | return errStopIterations 224 | } 225 | 226 | n = next 227 | 228 | i-- 229 | nodes[i] = n 230 | return nil 231 | }); err != nil { 232 | return len(labels) 233 | } 234 | 235 | return i 236 | } 237 | 238 | func (n *Node) copyBranch(labels []string, nodes []*Node) *Node { 239 | for i, p := range nodes { 240 | p = p.copy() 241 | if !n.hasValue && n.branches.isEmpty() { 242 | p.branches, _ = p.branches.rawDel(labels[i]) 243 | } else { 244 | p.branches = p.branches.rawInsert(labels[i], n) 245 | } 246 | 247 | n = p 248 | } 249 | 250 | return n 251 | } 252 | -------------------------------------------------------------------------------- /domaintree/domaintree.go: -------------------------------------------------------------------------------- 1 | // Package domaintree implements radix tree data structure for domain names. 2 | package domaintree 3 | 4 | import ( 5 | "errors" 6 | 7 | "github.com/infobloxopen/go-trees/dltree" 8 | "github.com/infobloxopen/go-trees/domain" 9 | ) 10 | 11 | // Node is a radix tree for domain names. 12 | type Node struct { 13 | branches *dltree.Tree 14 | 15 | hasValue bool 16 | value interface{} 17 | } 18 | 19 | // Pair represents a key-value pair returned by Enumerate method. 20 | type Pair struct { 21 | // Key is a human-readable representation of domain name. 22 | Key string 23 | // Value stores data related to the name. 24 | Value interface{} 25 | } 26 | 27 | var errStopIterations = errors.New("stop iterations") 28 | 29 | // Insert puts value using given domain as a key. The method returns new tree (old one remains unaffected). 30 | func (n *Node) Insert(d domain.Name, v interface{}) *Node { 31 | n = n.copy() 32 | r := n 33 | 34 | d.GetLabels(func(label string) error { 35 | item, ok := n.branches.RawGet(label) 36 | var next *Node 37 | if ok { 38 | next = item.(*Node).copy() 39 | } else { 40 | next = new(Node) 41 | } 42 | 43 | n.branches = n.branches.RawInsert(label, next) 44 | n = next 45 | 46 | return nil 47 | }) 48 | 49 | n.hasValue = true 50 | n.value = v 51 | 52 | return r 53 | } 54 | 55 | // InplaceInsert puts or replaces value using given domain as a key. The method inserts data directly to current tree so make sure you have exclusive access to it. 56 | func (n *Node) InplaceInsert(d domain.Name, v interface{}) { 57 | if n.branches == nil { 58 | n.branches = dltree.NewTree() 59 | } 60 | 61 | d.GetLabels(func(label string) error { 62 | item, ok := n.branches.RawGet(label) 63 | if ok { 64 | n = item.(*Node) 65 | } else { 66 | next := &Node{branches: dltree.NewTree()} 67 | n.branches.RawInplaceInsert(label, next) 68 | n = next 69 | } 70 | 71 | return nil 72 | }) 73 | 74 | n.hasValue = true 75 | n.value = v 76 | } 77 | 78 | // Enumerate returns key-value pairs in given tree. It lists domains in the same order for the same tree. 79 | func (n *Node) Enumerate() chan Pair { 80 | ch := make(chan Pair) 81 | 82 | go func() { 83 | defer close(ch) 84 | n.enumerate("", ch) 85 | }() 86 | 87 | return ch 88 | } 89 | 90 | // Get gets value for given domain which is equal to domain in the tree or is a subdomain of existing domain. 91 | func (n *Node) Get(d domain.Name) (interface{}, bool) { 92 | if n == nil { 93 | return nil, false 94 | } 95 | 96 | var value interface{} 97 | hasValue := false 98 | 99 | d.GetLabels(func(label string) error { 100 | item, ok := n.branches.RawGet(label) 101 | if !ok { 102 | return errStopIterations 103 | } 104 | 105 | n = item.(*Node) 106 | if n.hasValue { 107 | value = n.value 108 | hasValue = true 109 | } 110 | return nil 111 | }) 112 | 113 | return value, hasValue 114 | } 115 | 116 | // DeleteSubdomains removes current domain and all its subdomains if any. It returns new tree and flag if deletion indeed occurs. 117 | func (n *Node) DeleteSubdomains(d domain.Name) (*Node, bool) { 118 | if n == nil { 119 | return nil, false 120 | } 121 | 122 | var ( 123 | labels [domain.MaxLabels]string 124 | nodes [domain.MaxLabels]*Node 125 | ) 126 | 127 | i := n.getBranch(d, labels[:], nodes[:]) 128 | if i >= len(nodes) || !nodes[i].hasValue && n.branches.IsEmpty() { 129 | return n, false 130 | } 131 | 132 | i++ 133 | if i >= len(nodes) { 134 | return new(Node), true 135 | } 136 | 137 | n = nodes[i].copy() 138 | n.branches, _ = n.branches.RawDelete(labels[i]) 139 | i++ 140 | 141 | return n.copyBranch(labels[i:], nodes[i:]), true 142 | } 143 | 144 | // Delete removes current domain only. It returns new tree and flag if deletion indeed occurs. 145 | func (n *Node) Delete(d domain.Name) (*Node, bool) { 146 | if n == nil { 147 | return nil, false 148 | } 149 | 150 | var ( 151 | labels [domain.MaxLabels]string 152 | nodes [domain.MaxLabels]*Node 153 | ) 154 | 155 | i := n.getBranch(d, labels[:], nodes[:]) 156 | if i >= len(nodes) || !nodes[i].hasValue { 157 | return n, false 158 | } 159 | 160 | n = nodes[i] 161 | i++ 162 | 163 | branches := n.branches 164 | if i >= len(nodes) { 165 | if branches.IsEmpty() { 166 | return new(Node), true 167 | } 168 | 169 | return &Node{branches: branches}, true 170 | } 171 | 172 | n = nodes[i].copy() 173 | if branches.IsEmpty() { 174 | n.branches, _ = n.branches.RawDelete(labels[i]) 175 | } else { 176 | n.branches = n.branches.RawInsert(labels[i], &Node{branches: branches}) 177 | } 178 | i++ 179 | 180 | return n.copyBranch(labels[i:], nodes[i:]), true 181 | } 182 | 183 | func (n *Node) copy() *Node { 184 | if n == nil { 185 | return new(Node) 186 | } 187 | 188 | return &Node{ 189 | branches: n.branches, 190 | hasValue: n.hasValue, 191 | value: n.value, 192 | } 193 | } 194 | 195 | func (n *Node) enumerate(s string, ch chan Pair) { 196 | if n == nil { 197 | return 198 | } 199 | 200 | if n.hasValue { 201 | ch <- Pair{ 202 | Key: s, 203 | Value: n.value} 204 | } 205 | 206 | for item := range n.branches.Enumerate() { 207 | sub := item.Key 208 | if len(s) > 0 { 209 | sub += "." + s 210 | } 211 | node := item.Value.(*Node) 212 | 213 | node.enumerate(sub, ch) 214 | } 215 | } 216 | 217 | func (n *Node) getBranch(d domain.Name, labels []string, nodes []*Node) int { 218 | i := len(labels) - 1 219 | nodes[i] = n 220 | 221 | if err := d.GetLabels(func(label string) error { 222 | labels[i] = label 223 | 224 | next, ok := n.branches.RawGet(label) 225 | if !ok { 226 | return errStopIterations 227 | } 228 | 229 | n = next.(*Node) 230 | 231 | i-- 232 | nodes[i] = n 233 | return nil 234 | }); err != nil { 235 | return len(labels) 236 | } 237 | 238 | return i 239 | } 240 | 241 | func (n *Node) copyBranch(labels []string, nodes []*Node) *Node { 242 | for i, p := range nodes { 243 | p = p.copy() 244 | if !n.hasValue && n.branches.IsEmpty() { 245 | p.branches, _ = p.branches.RawDelete(labels[i]) 246 | } else { 247 | p.branches = p.branches.RawInsert(labels[i], n) 248 | } 249 | 250 | n = p 251 | } 252 | 253 | return n 254 | } 255 | -------------------------------------------------------------------------------- /uintX/iptree{{.bits}}/iptree.{{.ext}}: -------------------------------------------------------------------------------- 1 | // Package iptree{{.bits}} implements radix tree data structure for IPv4 and IPv6 networks as key and uint{{.bits}} as value. 2 | package iptree{{.bits}} 3 | 4 | // {{.warning}} 5 | 6 | import "net" 7 | 8 | const ( 9 | iPv4Bits = net.IPv4len * 8 10 | iPv6Bits = net.IPv6len * 8 11 | ) 12 | 13 | var ( 14 | iPv4MaxMask = net.CIDRMask(iPv4Bits, iPv4Bits) 15 | iPv6MaxMask = net.CIDRMask(iPv6Bits, iPv6Bits) 16 | ) 17 | 18 | // Tree is a radix tree for IPv4 and IPv6 networks. 19 | type Tree struct { 20 | root32 *node32 21 | root64 *node64s 22 | } 23 | 24 | // Pair represents a key-value pair returned by Enumerate method. 25 | type Pair struct { 26 | Key *net.IPNet 27 | Value uint{{.bits}} 28 | } 29 | 30 | type subTree64 *node64 31 | 32 | // NewTree creates empty tree. 33 | func NewTree() *Tree { 34 | return &Tree{} 35 | } 36 | 37 | // InsertNet inserts value using given network as a key. The method returns new tree (old one remains unaffected). 38 | func (t *Tree) InsertNet(n *net.IPNet, value uint{{.bits}}) *Tree { 39 | if n == nil { 40 | return t 41 | } 42 | 43 | var ( 44 | r32 *node32 45 | r64 *node64s 46 | ) 47 | 48 | if t != nil { 49 | r32 = t.root32 50 | r64 = t.root64 51 | } 52 | 53 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 54 | return &Tree{ 55 | root32: r32.Insert(key, bits, value), 56 | root64: r64, 57 | } 58 | } 59 | 60 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 61 | var r *node64 62 | if v, ok := r64.ExactMatch(MSKey, MSBits); ok { 63 | r = v 64 | } 65 | 66 | return &Tree{ 67 | root32: r32, 68 | root64: r64.Insert(MSKey, MSBits, r.Insert(LSKey, LSBits, value)), 69 | } 70 | } 71 | 72 | return t 73 | } 74 | 75 | // InplaceInsertNet inserts (or replaces) value using given network as a key in current tree. 76 | func (t *Tree) InplaceInsertNet(n *net.IPNet, value uint{{.bits}}) { 77 | if n == nil { 78 | return 79 | } 80 | 81 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 82 | t.root32 = t.root32.InplaceInsert(key, bits, value) 83 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 84 | var r *node64 85 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 86 | r = v.InplaceInsert(LSKey, LSBits, value) 87 | if r != v { 88 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r) 89 | } 90 | } else { 91 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r.InplaceInsert(LSKey, LSBits, value)) 92 | } 93 | } 94 | } 95 | 96 | // InsertIP inserts value using given IP address as a key. The method returns new tree (old one remains unaffected). 97 | func (t *Tree) InsertIP(ip net.IP, value uint{{.bits}}) *Tree { 98 | return t.InsertNet(newIPNetFromIP(ip), value) 99 | } 100 | 101 | // InplaceInsertIP inserts (or replaces) value using given IP address as a key in current tree. 102 | func (t *Tree) InplaceInsertIP(ip net.IP, value uint{{.bits}}) { 103 | t.InplaceInsertNet(newIPNetFromIP(ip), value) 104 | } 105 | 106 | // Enumerate returns channel which is populated by key-value pairs of tree content. 107 | func (t *Tree) Enumerate() chan Pair { 108 | ch := make(chan Pair) 109 | 110 | go func() { 111 | defer close(ch) 112 | 113 | if t == nil { 114 | return 115 | } 116 | 117 | t.enumerate(ch) 118 | }() 119 | 120 | return ch 121 | } 122 | 123 | // GetByNet gets value for network which is equal to or contains given network. 124 | func (t *Tree) GetByNet(n *net.IPNet) (uint{{.bits}}, bool) { 125 | if t == nil || n == nil { 126 | return 0, false 127 | } 128 | 129 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 130 | return t.root32.Match(key, bits) 131 | } 132 | 133 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 134 | s, ok := t.root64.Match(MSKey, MSBits) 135 | if !ok { 136 | return 0, false 137 | } 138 | 139 | v, ok := s.Match(LSKey, LSBits) 140 | if ok || MSBits < key64BitSize { 141 | return v, ok 142 | } 143 | 144 | s, ok = t.root64.Match(MSKey, MSBits-1) 145 | if !ok { 146 | return 0, false 147 | } 148 | 149 | return s.Match(LSKey, LSBits) 150 | } 151 | 152 | return 0, false 153 | } 154 | 155 | // GetByIP gets value for network which is equal to or contains given IP address. 156 | func (t *Tree) GetByIP(ip net.IP) (uint{{.bits}}, bool) { 157 | return t.GetByNet(newIPNetFromIP(ip)) 158 | } 159 | 160 | // DeleteByNet removes subtree which is contained by given network. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 161 | func (t *Tree) DeleteByNet(n *net.IPNet) (*Tree, bool) { 162 | if t == nil || n == nil { 163 | return t, false 164 | } 165 | 166 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 167 | r, ok := t.root32.Delete(key, bits) 168 | if ok { 169 | return &Tree{root32: r, root64: t.root64}, true 170 | } 171 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 172 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 173 | r, ok := v.Delete(LSKey, LSBits) 174 | if ok { 175 | r64 := t.root64 176 | if r == nil { 177 | r64, _ = r64.Delete(MSKey, MSBits) 178 | } else { 179 | r64 = r64.Insert(MSKey, MSBits, r) 180 | } 181 | 182 | return &Tree{root32: t.root32, root64: r64}, true 183 | } 184 | } 185 | } 186 | 187 | return t, false 188 | } 189 | 190 | // DeleteByIP removes node by given IP address. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 191 | func (t *Tree) DeleteByIP(ip net.IP) (*Tree, bool) { 192 | return t.DeleteByNet(newIPNetFromIP(ip)) 193 | } 194 | 195 | func (t *Tree) enumerate(ch chan Pair) { 196 | for n := range t.root32.Enumerate() { 197 | mask := net.CIDRMask(int(n.bits), iPv4Bits) 198 | ch <- Pair{ 199 | Key: &net.IPNet{ 200 | IP: unpackUint32ToIP(n.key).Mask(mask), 201 | Mask: mask}, 202 | Value: n.value} 203 | } 204 | 205 | for n := range t.root64.Enumerate() { 206 | MSIP := append(unpackUint64ToIP(n.key), make(net.IP, 8)...) 207 | for m := range n.value.Enumerate() { 208 | LSIP := unpackUint64ToIP(m.key) 209 | mask := net.CIDRMask(int(n.bits+m.bits), iPv6Bits) 210 | ch <- Pair{ 211 | Key: &net.IPNet{ 212 | IP: append(MSIP[0:8], LSIP...).Mask(mask), 213 | Mask: mask}, 214 | Value: m.value} 215 | } 216 | } 217 | } 218 | 219 | func iPv4NetToUint32(n *net.IPNet) (uint32, int) { 220 | if len(n.IP) != net.IPv4len { 221 | return 0, -1 222 | } 223 | 224 | ones, bits := n.Mask.Size() 225 | if bits != iPv4Bits { 226 | return 0, -1 227 | } 228 | 229 | return packIPToUint32(n.IP), ones 230 | } 231 | 232 | func packIPToUint32(x net.IP) uint32 { 233 | return (uint32(x[0]) << 24) | (uint32(x[1]) << 16) | (uint32(x[2]) << 8) | uint32(x[3]) 234 | } 235 | 236 | func unpackUint32ToIP(x uint32) net.IP { 237 | return net.IP{byte(x >> 24 & 0xff), byte(x >> 16 & 0xff), byte(x >> 8 & 0xff), byte(x & 0xff)} 238 | } 239 | 240 | func iPv6NetToUint64Pair(n *net.IPNet) (uint64, int, uint64, int) { 241 | if len(n.IP) != net.IPv6len { 242 | return 0, -1, 0, -1 243 | } 244 | 245 | ones, bits := n.Mask.Size() 246 | if bits != iPv6Bits { 247 | return 0, -1, 0, -1 248 | } 249 | 250 | MSBits := key64BitSize 251 | LSBits := 0 252 | if ones > key64BitSize { 253 | LSBits = ones - key64BitSize 254 | } else { 255 | MSBits = ones 256 | } 257 | 258 | return packIPToUint64(n.IP), MSBits, packIPToUint64(n.IP[8:]), LSBits 259 | } 260 | 261 | func packIPToUint64(x net.IP) uint64 { 262 | return (uint64(x[0]) << 56) | (uint64(x[1]) << 48) | (uint64(x[2]) << 40) | (uint64(x[3]) << 32) | 263 | (uint64(x[4]) << 24) | (uint64(x[5]) << 16) | (uint64(x[6]) << 8) | uint64(x[7]) 264 | } 265 | 266 | func unpackUint64ToIP(x uint64) net.IP { 267 | return net.IP{ 268 | byte(x >> 56 & 0xff), 269 | byte(x >> 48 & 0xff), 270 | byte(x >> 40 & 0xff), 271 | byte(x >> 32 & 0xff), 272 | byte(x >> 24 & 0xff), 273 | byte(x >> 16 & 0xff), 274 | byte(x >> 8 & 0xff), 275 | byte(x & 0xff)} 276 | } 277 | 278 | func newIPNetFromIP(ip net.IP) *net.IPNet { 279 | if ip4 := ip.To4(); ip4 != nil { 280 | return &net.IPNet{IP: ip4, Mask: iPv4MaxMask} 281 | } 282 | 283 | if ip6 := ip.To16(); ip6 != nil { 284 | return &net.IPNet{IP: ip6, Mask: iPv6MaxMask} 285 | } 286 | 287 | return nil 288 | } 289 | -------------------------------------------------------------------------------- /uintX/iptree8/iptree.go: -------------------------------------------------------------------------------- 1 | // Package iptree8 implements radix tree data structure for IPv4 and IPv6 networks as key and uint8 as value. 2 | package iptree8 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint8 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import "net" 7 | 8 | const ( 9 | iPv4Bits = net.IPv4len * 8 10 | iPv6Bits = net.IPv6len * 8 11 | ) 12 | 13 | var ( 14 | iPv4MaxMask = net.CIDRMask(iPv4Bits, iPv4Bits) 15 | iPv6MaxMask = net.CIDRMask(iPv6Bits, iPv6Bits) 16 | ) 17 | 18 | // Tree is a radix tree for IPv4 and IPv6 networks. 19 | type Tree struct { 20 | root32 *node32 21 | root64 *node64s 22 | } 23 | 24 | // Pair represents a key-value pair returned by Enumerate method. 25 | type Pair struct { 26 | Key *net.IPNet 27 | Value uint8 28 | } 29 | 30 | type subTree64 *node64 31 | 32 | // NewTree creates empty tree. 33 | func NewTree() *Tree { 34 | return &Tree{} 35 | } 36 | 37 | // InsertNet inserts value using given network as a key. The method returns new tree (old one remains unaffected). 38 | func (t *Tree) InsertNet(n *net.IPNet, value uint8) *Tree { 39 | if n == nil { 40 | return t 41 | } 42 | 43 | var ( 44 | r32 *node32 45 | r64 *node64s 46 | ) 47 | 48 | if t != nil { 49 | r32 = t.root32 50 | r64 = t.root64 51 | } 52 | 53 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 54 | return &Tree{ 55 | root32: r32.Insert(key, bits, value), 56 | root64: r64, 57 | } 58 | } 59 | 60 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 61 | var r *node64 62 | if v, ok := r64.ExactMatch(MSKey, MSBits); ok { 63 | r = v 64 | } 65 | 66 | return &Tree{ 67 | root32: r32, 68 | root64: r64.Insert(MSKey, MSBits, r.Insert(LSKey, LSBits, value)), 69 | } 70 | } 71 | 72 | return t 73 | } 74 | 75 | // InplaceInsertNet inserts (or replaces) value using given network as a key in current tree. 76 | func (t *Tree) InplaceInsertNet(n *net.IPNet, value uint8) { 77 | if n == nil { 78 | return 79 | } 80 | 81 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 82 | t.root32 = t.root32.InplaceInsert(key, bits, value) 83 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 84 | var r *node64 85 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 86 | r = v.InplaceInsert(LSKey, LSBits, value) 87 | if r != v { 88 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r) 89 | } 90 | } else { 91 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r.InplaceInsert(LSKey, LSBits, value)) 92 | } 93 | } 94 | } 95 | 96 | // InsertIP inserts value using given IP address as a key. The method returns new tree (old one remains unaffected). 97 | func (t *Tree) InsertIP(ip net.IP, value uint8) *Tree { 98 | return t.InsertNet(newIPNetFromIP(ip), value) 99 | } 100 | 101 | // InplaceInsertIP inserts (or replaces) value using given IP address as a key in current tree. 102 | func (t *Tree) InplaceInsertIP(ip net.IP, value uint8) { 103 | t.InplaceInsertNet(newIPNetFromIP(ip), value) 104 | } 105 | 106 | // Enumerate returns channel which is populated by key-value pairs of tree content. 107 | func (t *Tree) Enumerate() chan Pair { 108 | ch := make(chan Pair) 109 | 110 | go func() { 111 | defer close(ch) 112 | 113 | if t == nil { 114 | return 115 | } 116 | 117 | t.enumerate(ch) 118 | }() 119 | 120 | return ch 121 | } 122 | 123 | // GetByNet gets value for network which is equal to or contains given network. 124 | func (t *Tree) GetByNet(n *net.IPNet) (uint8, bool) { 125 | if t == nil || n == nil { 126 | return 0, false 127 | } 128 | 129 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 130 | return t.root32.Match(key, bits) 131 | } 132 | 133 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 134 | s, ok := t.root64.Match(MSKey, MSBits) 135 | if !ok { 136 | return 0, false 137 | } 138 | 139 | v, ok := s.Match(LSKey, LSBits) 140 | if ok || MSBits < key64BitSize { 141 | return v, ok 142 | } 143 | 144 | s, ok = t.root64.Match(MSKey, MSBits-1) 145 | if !ok { 146 | return 0, false 147 | } 148 | 149 | return s.Match(LSKey, LSBits) 150 | } 151 | 152 | return 0, false 153 | } 154 | 155 | // GetByIP gets value for network which is equal to or contains given IP address. 156 | func (t *Tree) GetByIP(ip net.IP) (uint8, bool) { 157 | return t.GetByNet(newIPNetFromIP(ip)) 158 | } 159 | 160 | // DeleteByNet removes subtree which is contained by given network. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 161 | func (t *Tree) DeleteByNet(n *net.IPNet) (*Tree, bool) { 162 | if t == nil || n == nil { 163 | return t, false 164 | } 165 | 166 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 167 | r, ok := t.root32.Delete(key, bits) 168 | if ok { 169 | return &Tree{root32: r, root64: t.root64}, true 170 | } 171 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 172 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 173 | r, ok := v.Delete(LSKey, LSBits) 174 | if ok { 175 | r64 := t.root64 176 | if r == nil { 177 | r64, _ = r64.Delete(MSKey, MSBits) 178 | } else { 179 | r64 = r64.Insert(MSKey, MSBits, r) 180 | } 181 | 182 | return &Tree{root32: t.root32, root64: r64}, true 183 | } 184 | } 185 | } 186 | 187 | return t, false 188 | } 189 | 190 | // DeleteByIP removes node by given IP address. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 191 | func (t *Tree) DeleteByIP(ip net.IP) (*Tree, bool) { 192 | return t.DeleteByNet(newIPNetFromIP(ip)) 193 | } 194 | 195 | func (t *Tree) enumerate(ch chan Pair) { 196 | for n := range t.root32.Enumerate() { 197 | mask := net.CIDRMask(int(n.bits), iPv4Bits) 198 | ch <- Pair{ 199 | Key: &net.IPNet{ 200 | IP: unpackUint32ToIP(n.key).Mask(mask), 201 | Mask: mask}, 202 | Value: n.value} 203 | } 204 | 205 | for n := range t.root64.Enumerate() { 206 | MSIP := append(unpackUint64ToIP(n.key), make(net.IP, 8)...) 207 | for m := range n.value.Enumerate() { 208 | LSIP := unpackUint64ToIP(m.key) 209 | mask := net.CIDRMask(int(n.bits+m.bits), iPv6Bits) 210 | ch <- Pair{ 211 | Key: &net.IPNet{ 212 | IP: append(MSIP[0:8], LSIP...).Mask(mask), 213 | Mask: mask}, 214 | Value: m.value} 215 | } 216 | } 217 | } 218 | 219 | func iPv4NetToUint32(n *net.IPNet) (uint32, int) { 220 | if len(n.IP) != net.IPv4len { 221 | return 0, -1 222 | } 223 | 224 | ones, bits := n.Mask.Size() 225 | if bits != iPv4Bits { 226 | return 0, -1 227 | } 228 | 229 | return packIPToUint32(n.IP), ones 230 | } 231 | 232 | func packIPToUint32(x net.IP) uint32 { 233 | return (uint32(x[0]) << 24) | (uint32(x[1]) << 16) | (uint32(x[2]) << 8) | uint32(x[3]) 234 | } 235 | 236 | func unpackUint32ToIP(x uint32) net.IP { 237 | return net.IP{byte(x >> 24 & 0xff), byte(x >> 16 & 0xff), byte(x >> 8 & 0xff), byte(x & 0xff)} 238 | } 239 | 240 | func iPv6NetToUint64Pair(n *net.IPNet) (uint64, int, uint64, int) { 241 | if len(n.IP) != net.IPv6len { 242 | return 0, -1, 0, -1 243 | } 244 | 245 | ones, bits := n.Mask.Size() 246 | if bits != iPv6Bits { 247 | return 0, -1, 0, -1 248 | } 249 | 250 | MSBits := key64BitSize 251 | LSBits := 0 252 | if ones > key64BitSize { 253 | LSBits = ones - key64BitSize 254 | } else { 255 | MSBits = ones 256 | } 257 | 258 | return packIPToUint64(n.IP), MSBits, packIPToUint64(n.IP[8:]), LSBits 259 | } 260 | 261 | func packIPToUint64(x net.IP) uint64 { 262 | return (uint64(x[0]) << 56) | (uint64(x[1]) << 48) | (uint64(x[2]) << 40) | (uint64(x[3]) << 32) | 263 | (uint64(x[4]) << 24) | (uint64(x[5]) << 16) | (uint64(x[6]) << 8) | uint64(x[7]) 264 | } 265 | 266 | func unpackUint64ToIP(x uint64) net.IP { 267 | return net.IP{ 268 | byte(x >> 56 & 0xff), 269 | byte(x >> 48 & 0xff), 270 | byte(x >> 40 & 0xff), 271 | byte(x >> 32 & 0xff), 272 | byte(x >> 24 & 0xff), 273 | byte(x >> 16 & 0xff), 274 | byte(x >> 8 & 0xff), 275 | byte(x & 0xff)} 276 | } 277 | 278 | func newIPNetFromIP(ip net.IP) *net.IPNet { 279 | if ip4 := ip.To4(); ip4 != nil { 280 | return &net.IPNet{IP: ip4, Mask: iPv4MaxMask} 281 | } 282 | 283 | if ip6 := ip.To16(); ip6 != nil { 284 | return &net.IPNet{IP: ip6, Mask: iPv6MaxMask} 285 | } 286 | 287 | return nil 288 | } 289 | -------------------------------------------------------------------------------- /uintX/iptree16/iptree.go: -------------------------------------------------------------------------------- 1 | // Package iptree16 implements radix tree data structure for IPv4 and IPv6 networks as key and uint16 as value. 2 | package iptree16 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint16 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import "net" 7 | 8 | const ( 9 | iPv4Bits = net.IPv4len * 8 10 | iPv6Bits = net.IPv6len * 8 11 | ) 12 | 13 | var ( 14 | iPv4MaxMask = net.CIDRMask(iPv4Bits, iPv4Bits) 15 | iPv6MaxMask = net.CIDRMask(iPv6Bits, iPv6Bits) 16 | ) 17 | 18 | // Tree is a radix tree for IPv4 and IPv6 networks. 19 | type Tree struct { 20 | root32 *node32 21 | root64 *node64s 22 | } 23 | 24 | // Pair represents a key-value pair returned by Enumerate method. 25 | type Pair struct { 26 | Key *net.IPNet 27 | Value uint16 28 | } 29 | 30 | type subTree64 *node64 31 | 32 | // NewTree creates empty tree. 33 | func NewTree() *Tree { 34 | return &Tree{} 35 | } 36 | 37 | // InsertNet inserts value using given network as a key. The method returns new tree (old one remains unaffected). 38 | func (t *Tree) InsertNet(n *net.IPNet, value uint16) *Tree { 39 | if n == nil { 40 | return t 41 | } 42 | 43 | var ( 44 | r32 *node32 45 | r64 *node64s 46 | ) 47 | 48 | if t != nil { 49 | r32 = t.root32 50 | r64 = t.root64 51 | } 52 | 53 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 54 | return &Tree{ 55 | root32: r32.Insert(key, bits, value), 56 | root64: r64, 57 | } 58 | } 59 | 60 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 61 | var r *node64 62 | if v, ok := r64.ExactMatch(MSKey, MSBits); ok { 63 | r = v 64 | } 65 | 66 | return &Tree{ 67 | root32: r32, 68 | root64: r64.Insert(MSKey, MSBits, r.Insert(LSKey, LSBits, value)), 69 | } 70 | } 71 | 72 | return t 73 | } 74 | 75 | // InplaceInsertNet inserts (or replaces) value using given network as a key in current tree. 76 | func (t *Tree) InplaceInsertNet(n *net.IPNet, value uint16) { 77 | if n == nil { 78 | return 79 | } 80 | 81 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 82 | t.root32 = t.root32.InplaceInsert(key, bits, value) 83 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 84 | var r *node64 85 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 86 | r = v.InplaceInsert(LSKey, LSBits, value) 87 | if r != v { 88 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r) 89 | } 90 | } else { 91 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r.InplaceInsert(LSKey, LSBits, value)) 92 | } 93 | } 94 | } 95 | 96 | // InsertIP inserts value using given IP address as a key. The method returns new tree (old one remains unaffected). 97 | func (t *Tree) InsertIP(ip net.IP, value uint16) *Tree { 98 | return t.InsertNet(newIPNetFromIP(ip), value) 99 | } 100 | 101 | // InplaceInsertIP inserts (or replaces) value using given IP address as a key in current tree. 102 | func (t *Tree) InplaceInsertIP(ip net.IP, value uint16) { 103 | t.InplaceInsertNet(newIPNetFromIP(ip), value) 104 | } 105 | 106 | // Enumerate returns channel which is populated by key-value pairs of tree content. 107 | func (t *Tree) Enumerate() chan Pair { 108 | ch := make(chan Pair) 109 | 110 | go func() { 111 | defer close(ch) 112 | 113 | if t == nil { 114 | return 115 | } 116 | 117 | t.enumerate(ch) 118 | }() 119 | 120 | return ch 121 | } 122 | 123 | // GetByNet gets value for network which is equal to or contains given network. 124 | func (t *Tree) GetByNet(n *net.IPNet) (uint16, bool) { 125 | if t == nil || n == nil { 126 | return 0, false 127 | } 128 | 129 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 130 | return t.root32.Match(key, bits) 131 | } 132 | 133 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 134 | s, ok := t.root64.Match(MSKey, MSBits) 135 | if !ok { 136 | return 0, false 137 | } 138 | 139 | v, ok := s.Match(LSKey, LSBits) 140 | if ok || MSBits < key64BitSize { 141 | return v, ok 142 | } 143 | 144 | s, ok = t.root64.Match(MSKey, MSBits-1) 145 | if !ok { 146 | return 0, false 147 | } 148 | 149 | return s.Match(LSKey, LSBits) 150 | } 151 | 152 | return 0, false 153 | } 154 | 155 | // GetByIP gets value for network which is equal to or contains given IP address. 156 | func (t *Tree) GetByIP(ip net.IP) (uint16, bool) { 157 | return t.GetByNet(newIPNetFromIP(ip)) 158 | } 159 | 160 | // DeleteByNet removes subtree which is contained by given network. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 161 | func (t *Tree) DeleteByNet(n *net.IPNet) (*Tree, bool) { 162 | if t == nil || n == nil { 163 | return t, false 164 | } 165 | 166 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 167 | r, ok := t.root32.Delete(key, bits) 168 | if ok { 169 | return &Tree{root32: r, root64: t.root64}, true 170 | } 171 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 172 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 173 | r, ok := v.Delete(LSKey, LSBits) 174 | if ok { 175 | r64 := t.root64 176 | if r == nil { 177 | r64, _ = r64.Delete(MSKey, MSBits) 178 | } else { 179 | r64 = r64.Insert(MSKey, MSBits, r) 180 | } 181 | 182 | return &Tree{root32: t.root32, root64: r64}, true 183 | } 184 | } 185 | } 186 | 187 | return t, false 188 | } 189 | 190 | // DeleteByIP removes node by given IP address. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 191 | func (t *Tree) DeleteByIP(ip net.IP) (*Tree, bool) { 192 | return t.DeleteByNet(newIPNetFromIP(ip)) 193 | } 194 | 195 | func (t *Tree) enumerate(ch chan Pair) { 196 | for n := range t.root32.Enumerate() { 197 | mask := net.CIDRMask(int(n.bits), iPv4Bits) 198 | ch <- Pair{ 199 | Key: &net.IPNet{ 200 | IP: unpackUint32ToIP(n.key).Mask(mask), 201 | Mask: mask}, 202 | Value: n.value} 203 | } 204 | 205 | for n := range t.root64.Enumerate() { 206 | MSIP := append(unpackUint64ToIP(n.key), make(net.IP, 8)...) 207 | for m := range n.value.Enumerate() { 208 | LSIP := unpackUint64ToIP(m.key) 209 | mask := net.CIDRMask(int(n.bits+m.bits), iPv6Bits) 210 | ch <- Pair{ 211 | Key: &net.IPNet{ 212 | IP: append(MSIP[0:8], LSIP...).Mask(mask), 213 | Mask: mask}, 214 | Value: m.value} 215 | } 216 | } 217 | } 218 | 219 | func iPv4NetToUint32(n *net.IPNet) (uint32, int) { 220 | if len(n.IP) != net.IPv4len { 221 | return 0, -1 222 | } 223 | 224 | ones, bits := n.Mask.Size() 225 | if bits != iPv4Bits { 226 | return 0, -1 227 | } 228 | 229 | return packIPToUint32(n.IP), ones 230 | } 231 | 232 | func packIPToUint32(x net.IP) uint32 { 233 | return (uint32(x[0]) << 24) | (uint32(x[1]) << 16) | (uint32(x[2]) << 8) | uint32(x[3]) 234 | } 235 | 236 | func unpackUint32ToIP(x uint32) net.IP { 237 | return net.IP{byte(x >> 24 & 0xff), byte(x >> 16 & 0xff), byte(x >> 8 & 0xff), byte(x & 0xff)} 238 | } 239 | 240 | func iPv6NetToUint64Pair(n *net.IPNet) (uint64, int, uint64, int) { 241 | if len(n.IP) != net.IPv6len { 242 | return 0, -1, 0, -1 243 | } 244 | 245 | ones, bits := n.Mask.Size() 246 | if bits != iPv6Bits { 247 | return 0, -1, 0, -1 248 | } 249 | 250 | MSBits := key64BitSize 251 | LSBits := 0 252 | if ones > key64BitSize { 253 | LSBits = ones - key64BitSize 254 | } else { 255 | MSBits = ones 256 | } 257 | 258 | return packIPToUint64(n.IP), MSBits, packIPToUint64(n.IP[8:]), LSBits 259 | } 260 | 261 | func packIPToUint64(x net.IP) uint64 { 262 | return (uint64(x[0]) << 56) | (uint64(x[1]) << 48) | (uint64(x[2]) << 40) | (uint64(x[3]) << 32) | 263 | (uint64(x[4]) << 24) | (uint64(x[5]) << 16) | (uint64(x[6]) << 8) | uint64(x[7]) 264 | } 265 | 266 | func unpackUint64ToIP(x uint64) net.IP { 267 | return net.IP{ 268 | byte(x >> 56 & 0xff), 269 | byte(x >> 48 & 0xff), 270 | byte(x >> 40 & 0xff), 271 | byte(x >> 32 & 0xff), 272 | byte(x >> 24 & 0xff), 273 | byte(x >> 16 & 0xff), 274 | byte(x >> 8 & 0xff), 275 | byte(x & 0xff)} 276 | } 277 | 278 | func newIPNetFromIP(ip net.IP) *net.IPNet { 279 | if ip4 := ip.To4(); ip4 != nil { 280 | return &net.IPNet{IP: ip4, Mask: iPv4MaxMask} 281 | } 282 | 283 | if ip6 := ip.To16(); ip6 != nil { 284 | return &net.IPNet{IP: ip6, Mask: iPv6MaxMask} 285 | } 286 | 287 | return nil 288 | } 289 | -------------------------------------------------------------------------------- /uintX/iptree32/iptree.go: -------------------------------------------------------------------------------- 1 | // Package iptree32 implements radix tree data structure for IPv4 and IPv6 networks as key and uint32 as value. 2 | package iptree32 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint32 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import "net" 7 | 8 | const ( 9 | iPv4Bits = net.IPv4len * 8 10 | iPv6Bits = net.IPv6len * 8 11 | ) 12 | 13 | var ( 14 | iPv4MaxMask = net.CIDRMask(iPv4Bits, iPv4Bits) 15 | iPv6MaxMask = net.CIDRMask(iPv6Bits, iPv6Bits) 16 | ) 17 | 18 | // Tree is a radix tree for IPv4 and IPv6 networks. 19 | type Tree struct { 20 | root32 *node32 21 | root64 *node64s 22 | } 23 | 24 | // Pair represents a key-value pair returned by Enumerate method. 25 | type Pair struct { 26 | Key *net.IPNet 27 | Value uint32 28 | } 29 | 30 | type subTree64 *node64 31 | 32 | // NewTree creates empty tree. 33 | func NewTree() *Tree { 34 | return &Tree{} 35 | } 36 | 37 | // InsertNet inserts value using given network as a key. The method returns new tree (old one remains unaffected). 38 | func (t *Tree) InsertNet(n *net.IPNet, value uint32) *Tree { 39 | if n == nil { 40 | return t 41 | } 42 | 43 | var ( 44 | r32 *node32 45 | r64 *node64s 46 | ) 47 | 48 | if t != nil { 49 | r32 = t.root32 50 | r64 = t.root64 51 | } 52 | 53 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 54 | return &Tree{ 55 | root32: r32.Insert(key, bits, value), 56 | root64: r64, 57 | } 58 | } 59 | 60 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 61 | var r *node64 62 | if v, ok := r64.ExactMatch(MSKey, MSBits); ok { 63 | r = v 64 | } 65 | 66 | return &Tree{ 67 | root32: r32, 68 | root64: r64.Insert(MSKey, MSBits, r.Insert(LSKey, LSBits, value)), 69 | } 70 | } 71 | 72 | return t 73 | } 74 | 75 | // InplaceInsertNet inserts (or replaces) value using given network as a key in current tree. 76 | func (t *Tree) InplaceInsertNet(n *net.IPNet, value uint32) { 77 | if n == nil { 78 | return 79 | } 80 | 81 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 82 | t.root32 = t.root32.InplaceInsert(key, bits, value) 83 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 84 | var r *node64 85 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 86 | r = v.InplaceInsert(LSKey, LSBits, value) 87 | if r != v { 88 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r) 89 | } 90 | } else { 91 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r.InplaceInsert(LSKey, LSBits, value)) 92 | } 93 | } 94 | } 95 | 96 | // InsertIP inserts value using given IP address as a key. The method returns new tree (old one remains unaffected). 97 | func (t *Tree) InsertIP(ip net.IP, value uint32) *Tree { 98 | return t.InsertNet(newIPNetFromIP(ip), value) 99 | } 100 | 101 | // InplaceInsertIP inserts (or replaces) value using given IP address as a key in current tree. 102 | func (t *Tree) InplaceInsertIP(ip net.IP, value uint32) { 103 | t.InplaceInsertNet(newIPNetFromIP(ip), value) 104 | } 105 | 106 | // Enumerate returns channel which is populated by key-value pairs of tree content. 107 | func (t *Tree) Enumerate() chan Pair { 108 | ch := make(chan Pair) 109 | 110 | go func() { 111 | defer close(ch) 112 | 113 | if t == nil { 114 | return 115 | } 116 | 117 | t.enumerate(ch) 118 | }() 119 | 120 | return ch 121 | } 122 | 123 | // GetByNet gets value for network which is equal to or contains given network. 124 | func (t *Tree) GetByNet(n *net.IPNet) (uint32, bool) { 125 | if t == nil || n == nil { 126 | return 0, false 127 | } 128 | 129 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 130 | return t.root32.Match(key, bits) 131 | } 132 | 133 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 134 | s, ok := t.root64.Match(MSKey, MSBits) 135 | if !ok { 136 | return 0, false 137 | } 138 | 139 | v, ok := s.Match(LSKey, LSBits) 140 | if ok || MSBits < key64BitSize { 141 | return v, ok 142 | } 143 | 144 | s, ok = t.root64.Match(MSKey, MSBits-1) 145 | if !ok { 146 | return 0, false 147 | } 148 | 149 | return s.Match(LSKey, LSBits) 150 | } 151 | 152 | return 0, false 153 | } 154 | 155 | // GetByIP gets value for network which is equal to or contains given IP address. 156 | func (t *Tree) GetByIP(ip net.IP) (uint32, bool) { 157 | return t.GetByNet(newIPNetFromIP(ip)) 158 | } 159 | 160 | // DeleteByNet removes subtree which is contained by given network. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 161 | func (t *Tree) DeleteByNet(n *net.IPNet) (*Tree, bool) { 162 | if t == nil || n == nil { 163 | return t, false 164 | } 165 | 166 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 167 | r, ok := t.root32.Delete(key, bits) 168 | if ok { 169 | return &Tree{root32: r, root64: t.root64}, true 170 | } 171 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 172 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 173 | r, ok := v.Delete(LSKey, LSBits) 174 | if ok { 175 | r64 := t.root64 176 | if r == nil { 177 | r64, _ = r64.Delete(MSKey, MSBits) 178 | } else { 179 | r64 = r64.Insert(MSKey, MSBits, r) 180 | } 181 | 182 | return &Tree{root32: t.root32, root64: r64}, true 183 | } 184 | } 185 | } 186 | 187 | return t, false 188 | } 189 | 190 | // DeleteByIP removes node by given IP address. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 191 | func (t *Tree) DeleteByIP(ip net.IP) (*Tree, bool) { 192 | return t.DeleteByNet(newIPNetFromIP(ip)) 193 | } 194 | 195 | func (t *Tree) enumerate(ch chan Pair) { 196 | for n := range t.root32.Enumerate() { 197 | mask := net.CIDRMask(int(n.bits), iPv4Bits) 198 | ch <- Pair{ 199 | Key: &net.IPNet{ 200 | IP: unpackUint32ToIP(n.key).Mask(mask), 201 | Mask: mask}, 202 | Value: n.value} 203 | } 204 | 205 | for n := range t.root64.Enumerate() { 206 | MSIP := append(unpackUint64ToIP(n.key), make(net.IP, 8)...) 207 | for m := range n.value.Enumerate() { 208 | LSIP := unpackUint64ToIP(m.key) 209 | mask := net.CIDRMask(int(n.bits+m.bits), iPv6Bits) 210 | ch <- Pair{ 211 | Key: &net.IPNet{ 212 | IP: append(MSIP[0:8], LSIP...).Mask(mask), 213 | Mask: mask}, 214 | Value: m.value} 215 | } 216 | } 217 | } 218 | 219 | func iPv4NetToUint32(n *net.IPNet) (uint32, int) { 220 | if len(n.IP) != net.IPv4len { 221 | return 0, -1 222 | } 223 | 224 | ones, bits := n.Mask.Size() 225 | if bits != iPv4Bits { 226 | return 0, -1 227 | } 228 | 229 | return packIPToUint32(n.IP), ones 230 | } 231 | 232 | func packIPToUint32(x net.IP) uint32 { 233 | return (uint32(x[0]) << 24) | (uint32(x[1]) << 16) | (uint32(x[2]) << 8) | uint32(x[3]) 234 | } 235 | 236 | func unpackUint32ToIP(x uint32) net.IP { 237 | return net.IP{byte(x >> 24 & 0xff), byte(x >> 16 & 0xff), byte(x >> 8 & 0xff), byte(x & 0xff)} 238 | } 239 | 240 | func iPv6NetToUint64Pair(n *net.IPNet) (uint64, int, uint64, int) { 241 | if len(n.IP) != net.IPv6len { 242 | return 0, -1, 0, -1 243 | } 244 | 245 | ones, bits := n.Mask.Size() 246 | if bits != iPv6Bits { 247 | return 0, -1, 0, -1 248 | } 249 | 250 | MSBits := key64BitSize 251 | LSBits := 0 252 | if ones > key64BitSize { 253 | LSBits = ones - key64BitSize 254 | } else { 255 | MSBits = ones 256 | } 257 | 258 | return packIPToUint64(n.IP), MSBits, packIPToUint64(n.IP[8:]), LSBits 259 | } 260 | 261 | func packIPToUint64(x net.IP) uint64 { 262 | return (uint64(x[0]) << 56) | (uint64(x[1]) << 48) | (uint64(x[2]) << 40) | (uint64(x[3]) << 32) | 263 | (uint64(x[4]) << 24) | (uint64(x[5]) << 16) | (uint64(x[6]) << 8) | uint64(x[7]) 264 | } 265 | 266 | func unpackUint64ToIP(x uint64) net.IP { 267 | return net.IP{ 268 | byte(x >> 56 & 0xff), 269 | byte(x >> 48 & 0xff), 270 | byte(x >> 40 & 0xff), 271 | byte(x >> 32 & 0xff), 272 | byte(x >> 24 & 0xff), 273 | byte(x >> 16 & 0xff), 274 | byte(x >> 8 & 0xff), 275 | byte(x & 0xff)} 276 | } 277 | 278 | func newIPNetFromIP(ip net.IP) *net.IPNet { 279 | if ip4 := ip.To4(); ip4 != nil { 280 | return &net.IPNet{IP: ip4, Mask: iPv4MaxMask} 281 | } 282 | 283 | if ip6 := ip.To16(); ip6 != nil { 284 | return &net.IPNet{IP: ip6, Mask: iPv6MaxMask} 285 | } 286 | 287 | return nil 288 | } 289 | -------------------------------------------------------------------------------- /uintX/iptree64/iptree.go: -------------------------------------------------------------------------------- 1 | // Package iptree64 implements radix tree data structure for IPv4 and IPv6 networks as key and uint64 as value. 2 | package iptree64 3 | 4 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint64 -d uintX.yaml -t ./tree\{\{.bits\}\} 5 | 6 | import "net" 7 | 8 | const ( 9 | iPv4Bits = net.IPv4len * 8 10 | iPv6Bits = net.IPv6len * 8 11 | ) 12 | 13 | var ( 14 | iPv4MaxMask = net.CIDRMask(iPv4Bits, iPv4Bits) 15 | iPv6MaxMask = net.CIDRMask(iPv6Bits, iPv6Bits) 16 | ) 17 | 18 | // Tree is a radix tree for IPv4 and IPv6 networks. 19 | type Tree struct { 20 | root32 *node32 21 | root64 *node64s 22 | } 23 | 24 | // Pair represents a key-value pair returned by Enumerate method. 25 | type Pair struct { 26 | Key *net.IPNet 27 | Value uint64 28 | } 29 | 30 | type subTree64 *node64 31 | 32 | // NewTree creates empty tree. 33 | func NewTree() *Tree { 34 | return &Tree{} 35 | } 36 | 37 | // InsertNet inserts value using given network as a key. The method returns new tree (old one remains unaffected). 38 | func (t *Tree) InsertNet(n *net.IPNet, value uint64) *Tree { 39 | if n == nil { 40 | return t 41 | } 42 | 43 | var ( 44 | r32 *node32 45 | r64 *node64s 46 | ) 47 | 48 | if t != nil { 49 | r32 = t.root32 50 | r64 = t.root64 51 | } 52 | 53 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 54 | return &Tree{ 55 | root32: r32.Insert(key, bits, value), 56 | root64: r64, 57 | } 58 | } 59 | 60 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 61 | var r *node64 62 | if v, ok := r64.ExactMatch(MSKey, MSBits); ok { 63 | r = v 64 | } 65 | 66 | return &Tree{ 67 | root32: r32, 68 | root64: r64.Insert(MSKey, MSBits, r.Insert(LSKey, LSBits, value)), 69 | } 70 | } 71 | 72 | return t 73 | } 74 | 75 | // InplaceInsertNet inserts (or replaces) value using given network as a key in current tree. 76 | func (t *Tree) InplaceInsertNet(n *net.IPNet, value uint64) { 77 | if n == nil { 78 | return 79 | } 80 | 81 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 82 | t.root32 = t.root32.InplaceInsert(key, bits, value) 83 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 84 | var r *node64 85 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 86 | r = v.InplaceInsert(LSKey, LSBits, value) 87 | if r != v { 88 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r) 89 | } 90 | } else { 91 | t.root64 = t.root64.InplaceInsert(MSKey, MSBits, r.InplaceInsert(LSKey, LSBits, value)) 92 | } 93 | } 94 | } 95 | 96 | // InsertIP inserts value using given IP address as a key. The method returns new tree (old one remains unaffected). 97 | func (t *Tree) InsertIP(ip net.IP, value uint64) *Tree { 98 | return t.InsertNet(newIPNetFromIP(ip), value) 99 | } 100 | 101 | // InplaceInsertIP inserts (or replaces) value using given IP address as a key in current tree. 102 | func (t *Tree) InplaceInsertIP(ip net.IP, value uint64) { 103 | t.InplaceInsertNet(newIPNetFromIP(ip), value) 104 | } 105 | 106 | // Enumerate returns channel which is populated by key-value pairs of tree content. 107 | func (t *Tree) Enumerate() chan Pair { 108 | ch := make(chan Pair) 109 | 110 | go func() { 111 | defer close(ch) 112 | 113 | if t == nil { 114 | return 115 | } 116 | 117 | t.enumerate(ch) 118 | }() 119 | 120 | return ch 121 | } 122 | 123 | // GetByNet gets value for network which is equal to or contains given network. 124 | func (t *Tree) GetByNet(n *net.IPNet) (uint64, bool) { 125 | if t == nil || n == nil { 126 | return 0, false 127 | } 128 | 129 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 130 | return t.root32.Match(key, bits) 131 | } 132 | 133 | if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 134 | s, ok := t.root64.Match(MSKey, MSBits) 135 | if !ok { 136 | return 0, false 137 | } 138 | 139 | v, ok := s.Match(LSKey, LSBits) 140 | if ok || MSBits < key64BitSize { 141 | return v, ok 142 | } 143 | 144 | s, ok = t.root64.Match(MSKey, MSBits-1) 145 | if !ok { 146 | return 0, false 147 | } 148 | 149 | return s.Match(LSKey, LSBits) 150 | } 151 | 152 | return 0, false 153 | } 154 | 155 | // GetByIP gets value for network which is equal to or contains given IP address. 156 | func (t *Tree) GetByIP(ip net.IP) (uint64, bool) { 157 | return t.GetByNet(newIPNetFromIP(ip)) 158 | } 159 | 160 | // DeleteByNet removes subtree which is contained by given network. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 161 | func (t *Tree) DeleteByNet(n *net.IPNet) (*Tree, bool) { 162 | if t == nil || n == nil { 163 | return t, false 164 | } 165 | 166 | if key, bits := iPv4NetToUint32(n); bits >= 0 { 167 | r, ok := t.root32.Delete(key, bits) 168 | if ok { 169 | return &Tree{root32: r, root64: t.root64}, true 170 | } 171 | } else if MSKey, MSBits, LSKey, LSBits := iPv6NetToUint64Pair(n); MSBits >= 0 { 172 | if v, ok := t.root64.ExactMatch(MSKey, MSBits); ok { 173 | r, ok := v.Delete(LSKey, LSBits) 174 | if ok { 175 | r64 := t.root64 176 | if r == nil { 177 | r64, _ = r64.Delete(MSKey, MSBits) 178 | } else { 179 | r64 = r64.Insert(MSKey, MSBits, r) 180 | } 181 | 182 | return &Tree{root32: t.root32, root64: r64}, true 183 | } 184 | } 185 | } 186 | 187 | return t, false 188 | } 189 | 190 | // DeleteByIP removes node by given IP address. The method returns new tree (old one remains unaffected) and flag indicating if deletion happens indeed. 191 | func (t *Tree) DeleteByIP(ip net.IP) (*Tree, bool) { 192 | return t.DeleteByNet(newIPNetFromIP(ip)) 193 | } 194 | 195 | func (t *Tree) enumerate(ch chan Pair) { 196 | for n := range t.root32.Enumerate() { 197 | mask := net.CIDRMask(int(n.bits), iPv4Bits) 198 | ch <- Pair{ 199 | Key: &net.IPNet{ 200 | IP: unpackUint32ToIP(n.key).Mask(mask), 201 | Mask: mask}, 202 | Value: n.value} 203 | } 204 | 205 | for n := range t.root64.Enumerate() { 206 | MSIP := append(unpackUint64ToIP(n.key), make(net.IP, 8)...) 207 | for m := range n.value.Enumerate() { 208 | LSIP := unpackUint64ToIP(m.key) 209 | mask := net.CIDRMask(int(n.bits+m.bits), iPv6Bits) 210 | ch <- Pair{ 211 | Key: &net.IPNet{ 212 | IP: append(MSIP[0:8], LSIP...).Mask(mask), 213 | Mask: mask}, 214 | Value: m.value} 215 | } 216 | } 217 | } 218 | 219 | func iPv4NetToUint32(n *net.IPNet) (uint32, int) { 220 | if len(n.IP) != net.IPv4len { 221 | return 0, -1 222 | } 223 | 224 | ones, bits := n.Mask.Size() 225 | if bits != iPv4Bits { 226 | return 0, -1 227 | } 228 | 229 | return packIPToUint32(n.IP), ones 230 | } 231 | 232 | func packIPToUint32(x net.IP) uint32 { 233 | return (uint32(x[0]) << 24) | (uint32(x[1]) << 16) | (uint32(x[2]) << 8) | uint32(x[3]) 234 | } 235 | 236 | func unpackUint32ToIP(x uint32) net.IP { 237 | return net.IP{byte(x >> 24 & 0xff), byte(x >> 16 & 0xff), byte(x >> 8 & 0xff), byte(x & 0xff)} 238 | } 239 | 240 | func iPv6NetToUint64Pair(n *net.IPNet) (uint64, int, uint64, int) { 241 | if len(n.IP) != net.IPv6len { 242 | return 0, -1, 0, -1 243 | } 244 | 245 | ones, bits := n.Mask.Size() 246 | if bits != iPv6Bits { 247 | return 0, -1, 0, -1 248 | } 249 | 250 | MSBits := key64BitSize 251 | LSBits := 0 252 | if ones > key64BitSize { 253 | LSBits = ones - key64BitSize 254 | } else { 255 | MSBits = ones 256 | } 257 | 258 | return packIPToUint64(n.IP), MSBits, packIPToUint64(n.IP[8:]), LSBits 259 | } 260 | 261 | func packIPToUint64(x net.IP) uint64 { 262 | return (uint64(x[0]) << 56) | (uint64(x[1]) << 48) | (uint64(x[2]) << 40) | (uint64(x[3]) << 32) | 263 | (uint64(x[4]) << 24) | (uint64(x[5]) << 16) | (uint64(x[6]) << 8) | uint64(x[7]) 264 | } 265 | 266 | func unpackUint64ToIP(x uint64) net.IP { 267 | return net.IP{ 268 | byte(x >> 56 & 0xff), 269 | byte(x >> 48 & 0xff), 270 | byte(x >> 40 & 0xff), 271 | byte(x >> 32 & 0xff), 272 | byte(x >> 24 & 0xff), 273 | byte(x >> 16 & 0xff), 274 | byte(x >> 8 & 0xff), 275 | byte(x & 0xff)} 276 | } 277 | 278 | func newIPNetFromIP(ip net.IP) *net.IPNet { 279 | if ip4 := ip.To4(); ip4 != nil { 280 | return &net.IPNet{IP: ip4, Mask: iPv4MaxMask} 281 | } 282 | 283 | if ip6 := ip.To16(); ip6 != nil { 284 | return &net.IPNet{IP: ip6, Mask: iPv6MaxMask} 285 | } 286 | 287 | return nil 288 | } 289 | -------------------------------------------------------------------------------- /uintX/iptree{{.bits}}/node64s.{{.ext}}: -------------------------------------------------------------------------------- 1 | package iptree{{.bits}} 2 | 3 | // {{.warning}} 4 | 5 | import ( 6 | "fmt" 7 | "math/bits" 8 | ) 9 | 10 | // node64s is an element of radix tree with 64-bit unsigned integer as a key. 11 | type node64s struct { 12 | // key stores key for current node. 13 | key uint64 14 | // bits is a number of significant bits in key. 15 | bits uint8 16 | // leaf indicates if the node is leaf node and contains any data in value. 17 | leaf bool 18 | // value contains data associated with key. 19 | value *node64 20 | 21 | chld [2]*node64s 22 | } 23 | 24 | // Dot dumps tree to Graphviz .dot format 25 | func (n *node64s) Dot() string { 26 | body := "" 27 | 28 | i := 0 29 | queue := []*node64s{n} 30 | for len(queue) > 0 { 31 | c := queue[0] 32 | body += fmt.Sprintf("N%d %s\n", i, c.dotString()) 33 | 34 | if c != nil && (c.chld[0] != nil || c.chld[1] != nil) { 35 | body += fmt.Sprintf("N%d -> { N%d N%d }\n", i, i+len(queue), i+len(queue)+1) 36 | queue = append(append(queue, c.chld[0]), c.chld[1]) 37 | } 38 | 39 | queue = queue[1:] 40 | i++ 41 | } 42 | 43 | return "digraph d {\n" + body + "}\n" 44 | } 45 | 46 | // Insert puts new leaf to radix tree and returns pointer to new root. The method uses copy on write strategy so old root doesn't see the change. 47 | func (n *node64s) Insert(key uint64, bits int, value *node64) *node64s { 48 | if bits < 0 { 49 | bits = 0 50 | } else if bits > key64BitSize { 51 | bits = key64BitSize 52 | } 53 | 54 | return n.insert(newNode64s(key, uint8(bits), true, value)) 55 | } 56 | 57 | // InplaceInsert puts new leaf to radix tree (or replaces value in existing one). The method inserts data directly to current tree so make sure you have exclusive access to it. 58 | func (n *node64s) InplaceInsert(key uint64, bits int, value *node64) *node64s { 59 | // Adjust bits. 60 | if bits < 0 { 61 | bits = 0 62 | } else if bits > key64BitSize { 63 | bits = key64BitSize 64 | } 65 | 66 | return n.inplaceInsert(key, uint8(bits), value) 67 | } 68 | 69 | // Enumerate returns channel which is populated by nodes in order of their keys. 70 | func (n *node64s) Enumerate() chan *node64s { 71 | ch := make(chan *node64s) 72 | 73 | go func() { 74 | defer close(ch) 75 | 76 | if n == nil { 77 | return 78 | } 79 | 80 | n.enumerate(ch) 81 | }() 82 | 83 | return ch 84 | } 85 | 86 | // Match locates node which key is equal to or "contains" the key passed as argument. 87 | func (n *node64s) Match(key uint64, bits int) (*node64, bool) { 88 | if n == nil { 89 | return nil, false 90 | } 91 | 92 | if bits < 0 { 93 | bits = 0 94 | } else if bits > key64BitSize { 95 | bits = key64BitSize 96 | } 97 | 98 | r := n.match(key, uint8(bits)) 99 | if r == nil { 100 | return nil, false 101 | } 102 | 103 | return r.value, true 104 | } 105 | 106 | // ExactMatch locates node which exactly matches given key. 107 | func (n *node64s) ExactMatch(key uint64, bits int) (*node64, bool) { 108 | if n == nil { 109 | return nil, false 110 | } 111 | 112 | if bits < 0 { 113 | bits = 0 114 | } else if bits > key64BitSize { 115 | bits = key64BitSize 116 | } 117 | 118 | r := n.exactMatch(key, uint8(bits)) 119 | if r == nil { 120 | return nil, false 121 | } 122 | 123 | return r.value, true 124 | } 125 | 126 | // Delete removes subtree which is contained by given key. The method uses copy on write strategy. 127 | func (n *node64s) Delete(key uint64, bits int) (*node64s, bool) { 128 | if n == nil { 129 | return n, false 130 | } 131 | 132 | if bits < 0 { 133 | bits = 0 134 | } else if bits > key64BitSize { 135 | bits = key64BitSize 136 | } 137 | 138 | return n.del(key, uint8(bits)) 139 | } 140 | 141 | func (n *node64s) dotString() string { 142 | if n == nil { 143 | return "[label=\"nil\"]" 144 | } 145 | 146 | if n.leaf { 147 | return fmt.Sprintf("[label=\"k: %016x, b: %d, v: \\\"%p\\\"\"]", n.key, n.bits, n.value) 148 | } 149 | 150 | return fmt.Sprintf("[label=\"k: %016x, b: %d\"]", n.key, n.bits) 151 | } 152 | 153 | func (n *node64s) insert(c *node64s) *node64s { 154 | if n == nil { 155 | return c 156 | } 157 | 158 | bits := uint8(bits.LeadingZeros64((n.key ^ c.key) | ^masks64[n.bits] | ^masks64[c.bits])) 159 | if bits < n.bits { 160 | branch := (n.key >> (key64BitSize - 1 - bits)) & 1 161 | if bits == c.bits { 162 | c.chld[branch] = n 163 | return c 164 | } 165 | 166 | m := newNode64s(c.key&masks64[bits], bits, false, nil) 167 | m.chld[branch] = n 168 | m.chld[1-branch] = c 169 | 170 | return m 171 | } 172 | 173 | if c.bits == n.bits { 174 | c.chld = n.chld 175 | return c 176 | } 177 | 178 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 179 | m.chld = n.chld 180 | 181 | branch := (c.key >> (key64BitSize - 1 - bits)) & 1 182 | m.chld[branch] = m.chld[branch].insert(c) 183 | 184 | return m 185 | } 186 | 187 | func (n *node64s) inplaceInsert(key uint64, sbits uint8, value *node64) *node64s { 188 | var ( 189 | p *node64s 190 | branch uint64 191 | ) 192 | 193 | r := n 194 | 195 | for n != nil { 196 | cbits := uint8(bits.LeadingZeros64((n.key ^ key) | ^masks64[n.bits] | ^masks64[sbits])) 197 | if cbits < n.bits { 198 | pBranch := branch 199 | branch = (n.key >> (key64BitSize - 1 - cbits)) & 1 200 | 201 | var m *node64s 202 | 203 | if cbits == sbits { 204 | m = newNode64s(key, sbits, true, value) 205 | m.chld[branch] = n 206 | } else { 207 | m = newNode64s(key&masks64[cbits], cbits, false, nil) 208 | m.chld[1-branch] = newNode64s(key, sbits, true, value) 209 | } 210 | 211 | m.chld[branch] = n 212 | if p == nil { 213 | r = m 214 | } else { 215 | p.chld[pBranch] = m 216 | } 217 | 218 | return r 219 | } 220 | 221 | if sbits == n.bits { 222 | n.key = key 223 | n.leaf = true 224 | n.value = value 225 | return r 226 | } 227 | 228 | p = n 229 | branch = (key >> (key64BitSize - 1 - cbits)) & 1 230 | n = n.chld[branch] 231 | } 232 | 233 | n = newNode64s(key, sbits, true, value) 234 | if p == nil { 235 | return n 236 | } 237 | 238 | p.chld[branch] = n 239 | return r 240 | } 241 | 242 | func (n *node64s) enumerate(ch chan *node64s) { 243 | if n.leaf { 244 | ch <- n 245 | } 246 | 247 | if n.chld[0] != nil { 248 | n.chld[0].enumerate(ch) 249 | } 250 | 251 | if n.chld[1] != nil { 252 | n.chld[1].enumerate(ch) 253 | } 254 | } 255 | 256 | func (n *node64s) match(key uint64, bits uint8) *node64s { 257 | if n.bits > bits { 258 | return nil 259 | } 260 | 261 | if n.bits == bits { 262 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 263 | return n 264 | } 265 | 266 | return nil 267 | } 268 | 269 | if (n.key^key)&masks64[n.bits] != 0 { 270 | return nil 271 | } 272 | 273 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 274 | if c != nil { 275 | r := c.match(key, bits) 276 | if r != nil { 277 | return r 278 | } 279 | } 280 | 281 | if n.leaf { 282 | return n 283 | } 284 | 285 | return nil 286 | } 287 | 288 | func (n *node64s) exactMatch(key uint64, bits uint8) *node64s { 289 | if n.bits > bits { 290 | return nil 291 | } 292 | 293 | if n.bits == bits { 294 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 295 | return n 296 | } 297 | 298 | return nil 299 | } 300 | 301 | if (n.key^key)&masks64[n.bits] != 0 { 302 | return nil 303 | } 304 | 305 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 306 | if c != nil { 307 | r := c.exactMatch(key, bits) 308 | if r != nil { 309 | return r 310 | } 311 | } 312 | 313 | return nil 314 | } 315 | 316 | func (n *node64s) del(key uint64, bits uint8) (*node64s, bool) { 317 | if bits <= n.bits { 318 | if (n.key^key)&masks64[bits] == 0 { 319 | return nil, true 320 | } 321 | 322 | return n, false 323 | } 324 | 325 | if (n.key^key)&masks64[n.bits] != 0 { 326 | return n, false 327 | } 328 | 329 | branch := (key >> (key64BitSize - 1 - n.bits)) & 1 330 | c := n.chld[branch] 331 | if c == nil { 332 | return n, false 333 | } 334 | 335 | c, ok := c.del(key, bits) 336 | if !ok { 337 | return n, false 338 | } 339 | 340 | if c == nil && !n.leaf { 341 | return n.chld[1-branch], true 342 | } 343 | 344 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 345 | m.chld = n.chld 346 | 347 | m.chld[branch] = c 348 | return m, true 349 | } 350 | 351 | func newNode64s(key uint64, bits uint8, leaf bool, value *node64) *node64s { 352 | return &node64s{ 353 | key: key, 354 | bits: bits, 355 | leaf: leaf, 356 | value: value} 357 | } 358 | -------------------------------------------------------------------------------- /uintX/iptree8/node64s.go: -------------------------------------------------------------------------------- 1 | package iptree8 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint8 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import ( 6 | "fmt" 7 | "math/bits" 8 | ) 9 | 10 | // node64s is an element of radix tree with 64-bit unsigned integer as a key. 11 | type node64s struct { 12 | // key stores key for current node. 13 | key uint64 14 | // bits is a number of significant bits in key. 15 | bits uint8 16 | // leaf indicates if the node is leaf node and contains any data in value. 17 | leaf bool 18 | // value contains data associated with key. 19 | value *node64 20 | 21 | chld [2]*node64s 22 | } 23 | 24 | // Dot dumps tree to Graphviz .dot format 25 | func (n *node64s) Dot() string { 26 | body := "" 27 | 28 | i := 0 29 | queue := []*node64s{n} 30 | for len(queue) > 0 { 31 | c := queue[0] 32 | body += fmt.Sprintf("N%d %s\n", i, c.dotString()) 33 | 34 | if c != nil && (c.chld[0] != nil || c.chld[1] != nil) { 35 | body += fmt.Sprintf("N%d -> { N%d N%d }\n", i, i+len(queue), i+len(queue)+1) 36 | queue = append(append(queue, c.chld[0]), c.chld[1]) 37 | } 38 | 39 | queue = queue[1:] 40 | i++ 41 | } 42 | 43 | return "digraph d {\n" + body + "}\n" 44 | } 45 | 46 | // Insert puts new leaf to radix tree and returns pointer to new root. The method uses copy on write strategy so old root doesn't see the change. 47 | func (n *node64s) Insert(key uint64, bits int, value *node64) *node64s { 48 | if bits < 0 { 49 | bits = 0 50 | } else if bits > key64BitSize { 51 | bits = key64BitSize 52 | } 53 | 54 | return n.insert(newNode64s(key, uint8(bits), true, value)) 55 | } 56 | 57 | // InplaceInsert puts new leaf to radix tree (or replaces value in existing one). The method inserts data directly to current tree so make sure you have exclusive access to it. 58 | func (n *node64s) InplaceInsert(key uint64, bits int, value *node64) *node64s { 59 | // Adjust bits. 60 | if bits < 0 { 61 | bits = 0 62 | } else if bits > key64BitSize { 63 | bits = key64BitSize 64 | } 65 | 66 | return n.inplaceInsert(key, uint8(bits), value) 67 | } 68 | 69 | // Enumerate returns channel which is populated by nodes in order of their keys. 70 | func (n *node64s) Enumerate() chan *node64s { 71 | ch := make(chan *node64s) 72 | 73 | go func() { 74 | defer close(ch) 75 | 76 | if n == nil { 77 | return 78 | } 79 | 80 | n.enumerate(ch) 81 | }() 82 | 83 | return ch 84 | } 85 | 86 | // Match locates node which key is equal to or "contains" the key passed as argument. 87 | func (n *node64s) Match(key uint64, bits int) (*node64, bool) { 88 | if n == nil { 89 | return nil, false 90 | } 91 | 92 | if bits < 0 { 93 | bits = 0 94 | } else if bits > key64BitSize { 95 | bits = key64BitSize 96 | } 97 | 98 | r := n.match(key, uint8(bits)) 99 | if r == nil { 100 | return nil, false 101 | } 102 | 103 | return r.value, true 104 | } 105 | 106 | // ExactMatch locates node which exactly matches given key. 107 | func (n *node64s) ExactMatch(key uint64, bits int) (*node64, bool) { 108 | if n == nil { 109 | return nil, false 110 | } 111 | 112 | if bits < 0 { 113 | bits = 0 114 | } else if bits > key64BitSize { 115 | bits = key64BitSize 116 | } 117 | 118 | r := n.exactMatch(key, uint8(bits)) 119 | if r == nil { 120 | return nil, false 121 | } 122 | 123 | return r.value, true 124 | } 125 | 126 | // Delete removes subtree which is contained by given key. The method uses copy on write strategy. 127 | func (n *node64s) Delete(key uint64, bits int) (*node64s, bool) { 128 | if n == nil { 129 | return n, false 130 | } 131 | 132 | if bits < 0 { 133 | bits = 0 134 | } else if bits > key64BitSize { 135 | bits = key64BitSize 136 | } 137 | 138 | return n.del(key, uint8(bits)) 139 | } 140 | 141 | func (n *node64s) dotString() string { 142 | if n == nil { 143 | return "[label=\"nil\"]" 144 | } 145 | 146 | if n.leaf { 147 | return fmt.Sprintf("[label=\"k: %016x, b: %d, v: \\\"%p\\\"\"]", n.key, n.bits, n.value) 148 | } 149 | 150 | return fmt.Sprintf("[label=\"k: %016x, b: %d\"]", n.key, n.bits) 151 | } 152 | 153 | func (n *node64s) insert(c *node64s) *node64s { 154 | if n == nil { 155 | return c 156 | } 157 | 158 | bits := uint8(bits.LeadingZeros64((n.key ^ c.key) | ^masks64[n.bits] | ^masks64[c.bits])) 159 | if bits < n.bits { 160 | branch := (n.key >> (key64BitSize - 1 - bits)) & 1 161 | if bits == c.bits { 162 | c.chld[branch] = n 163 | return c 164 | } 165 | 166 | m := newNode64s(c.key&masks64[bits], bits, false, nil) 167 | m.chld[branch] = n 168 | m.chld[1-branch] = c 169 | 170 | return m 171 | } 172 | 173 | if c.bits == n.bits { 174 | c.chld = n.chld 175 | return c 176 | } 177 | 178 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 179 | m.chld = n.chld 180 | 181 | branch := (c.key >> (key64BitSize - 1 - bits)) & 1 182 | m.chld[branch] = m.chld[branch].insert(c) 183 | 184 | return m 185 | } 186 | 187 | func (n *node64s) inplaceInsert(key uint64, sbits uint8, value *node64) *node64s { 188 | var ( 189 | p *node64s 190 | branch uint64 191 | ) 192 | 193 | r := n 194 | 195 | for n != nil { 196 | cbits := uint8(bits.LeadingZeros64((n.key ^ key) | ^masks64[n.bits] | ^masks64[sbits])) 197 | if cbits < n.bits { 198 | pBranch := branch 199 | branch = (n.key >> (key64BitSize - 1 - cbits)) & 1 200 | 201 | var m *node64s 202 | 203 | if cbits == sbits { 204 | m = newNode64s(key, sbits, true, value) 205 | m.chld[branch] = n 206 | } else { 207 | m = newNode64s(key&masks64[cbits], cbits, false, nil) 208 | m.chld[1-branch] = newNode64s(key, sbits, true, value) 209 | } 210 | 211 | m.chld[branch] = n 212 | if p == nil { 213 | r = m 214 | } else { 215 | p.chld[pBranch] = m 216 | } 217 | 218 | return r 219 | } 220 | 221 | if sbits == n.bits { 222 | n.key = key 223 | n.leaf = true 224 | n.value = value 225 | return r 226 | } 227 | 228 | p = n 229 | branch = (key >> (key64BitSize - 1 - cbits)) & 1 230 | n = n.chld[branch] 231 | } 232 | 233 | n = newNode64s(key, sbits, true, value) 234 | if p == nil { 235 | return n 236 | } 237 | 238 | p.chld[branch] = n 239 | return r 240 | } 241 | 242 | func (n *node64s) enumerate(ch chan *node64s) { 243 | if n.leaf { 244 | ch <- n 245 | } 246 | 247 | if n.chld[0] != nil { 248 | n.chld[0].enumerate(ch) 249 | } 250 | 251 | if n.chld[1] != nil { 252 | n.chld[1].enumerate(ch) 253 | } 254 | } 255 | 256 | func (n *node64s) match(key uint64, bits uint8) *node64s { 257 | if n.bits > bits { 258 | return nil 259 | } 260 | 261 | if n.bits == bits { 262 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 263 | return n 264 | } 265 | 266 | return nil 267 | } 268 | 269 | if (n.key^key)&masks64[n.bits] != 0 { 270 | return nil 271 | } 272 | 273 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 274 | if c != nil { 275 | r := c.match(key, bits) 276 | if r != nil { 277 | return r 278 | } 279 | } 280 | 281 | if n.leaf { 282 | return n 283 | } 284 | 285 | return nil 286 | } 287 | 288 | func (n *node64s) exactMatch(key uint64, bits uint8) *node64s { 289 | if n.bits > bits { 290 | return nil 291 | } 292 | 293 | if n.bits == bits { 294 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 295 | return n 296 | } 297 | 298 | return nil 299 | } 300 | 301 | if (n.key^key)&masks64[n.bits] != 0 { 302 | return nil 303 | } 304 | 305 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 306 | if c != nil { 307 | r := c.exactMatch(key, bits) 308 | if r != nil { 309 | return r 310 | } 311 | } 312 | 313 | return nil 314 | } 315 | 316 | func (n *node64s) del(key uint64, bits uint8) (*node64s, bool) { 317 | if bits <= n.bits { 318 | if (n.key^key)&masks64[bits] == 0 { 319 | return nil, true 320 | } 321 | 322 | return n, false 323 | } 324 | 325 | if (n.key^key)&masks64[n.bits] != 0 { 326 | return n, false 327 | } 328 | 329 | branch := (key >> (key64BitSize - 1 - n.bits)) & 1 330 | c := n.chld[branch] 331 | if c == nil { 332 | return n, false 333 | } 334 | 335 | c, ok := c.del(key, bits) 336 | if !ok { 337 | return n, false 338 | } 339 | 340 | if c == nil && !n.leaf { 341 | return n.chld[1-branch], true 342 | } 343 | 344 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 345 | m.chld = n.chld 346 | 347 | m.chld[branch] = c 348 | return m, true 349 | } 350 | 351 | func newNode64s(key uint64, bits uint8, leaf bool, value *node64) *node64s { 352 | return &node64s{ 353 | key: key, 354 | bits: bits, 355 | leaf: leaf, 356 | value: value} 357 | } 358 | -------------------------------------------------------------------------------- /uintX/iptree16/node64s.go: -------------------------------------------------------------------------------- 1 | package iptree16 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint16 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import ( 6 | "fmt" 7 | "math/bits" 8 | ) 9 | 10 | // node64s is an element of radix tree with 64-bit unsigned integer as a key. 11 | type node64s struct { 12 | // key stores key for current node. 13 | key uint64 14 | // bits is a number of significant bits in key. 15 | bits uint8 16 | // leaf indicates if the node is leaf node and contains any data in value. 17 | leaf bool 18 | // value contains data associated with key. 19 | value *node64 20 | 21 | chld [2]*node64s 22 | } 23 | 24 | // Dot dumps tree to Graphviz .dot format 25 | func (n *node64s) Dot() string { 26 | body := "" 27 | 28 | i := 0 29 | queue := []*node64s{n} 30 | for len(queue) > 0 { 31 | c := queue[0] 32 | body += fmt.Sprintf("N%d %s\n", i, c.dotString()) 33 | 34 | if c != nil && (c.chld[0] != nil || c.chld[1] != nil) { 35 | body += fmt.Sprintf("N%d -> { N%d N%d }\n", i, i+len(queue), i+len(queue)+1) 36 | queue = append(append(queue, c.chld[0]), c.chld[1]) 37 | } 38 | 39 | queue = queue[1:] 40 | i++ 41 | } 42 | 43 | return "digraph d {\n" + body + "}\n" 44 | } 45 | 46 | // Insert puts new leaf to radix tree and returns pointer to new root. The method uses copy on write strategy so old root doesn't see the change. 47 | func (n *node64s) Insert(key uint64, bits int, value *node64) *node64s { 48 | if bits < 0 { 49 | bits = 0 50 | } else if bits > key64BitSize { 51 | bits = key64BitSize 52 | } 53 | 54 | return n.insert(newNode64s(key, uint8(bits), true, value)) 55 | } 56 | 57 | // InplaceInsert puts new leaf to radix tree (or replaces value in existing one). The method inserts data directly to current tree so make sure you have exclusive access to it. 58 | func (n *node64s) InplaceInsert(key uint64, bits int, value *node64) *node64s { 59 | // Adjust bits. 60 | if bits < 0 { 61 | bits = 0 62 | } else if bits > key64BitSize { 63 | bits = key64BitSize 64 | } 65 | 66 | return n.inplaceInsert(key, uint8(bits), value) 67 | } 68 | 69 | // Enumerate returns channel which is populated by nodes in order of their keys. 70 | func (n *node64s) Enumerate() chan *node64s { 71 | ch := make(chan *node64s) 72 | 73 | go func() { 74 | defer close(ch) 75 | 76 | if n == nil { 77 | return 78 | } 79 | 80 | n.enumerate(ch) 81 | }() 82 | 83 | return ch 84 | } 85 | 86 | // Match locates node which key is equal to or "contains" the key passed as argument. 87 | func (n *node64s) Match(key uint64, bits int) (*node64, bool) { 88 | if n == nil { 89 | return nil, false 90 | } 91 | 92 | if bits < 0 { 93 | bits = 0 94 | } else if bits > key64BitSize { 95 | bits = key64BitSize 96 | } 97 | 98 | r := n.match(key, uint8(bits)) 99 | if r == nil { 100 | return nil, false 101 | } 102 | 103 | return r.value, true 104 | } 105 | 106 | // ExactMatch locates node which exactly matches given key. 107 | func (n *node64s) ExactMatch(key uint64, bits int) (*node64, bool) { 108 | if n == nil { 109 | return nil, false 110 | } 111 | 112 | if bits < 0 { 113 | bits = 0 114 | } else if bits > key64BitSize { 115 | bits = key64BitSize 116 | } 117 | 118 | r := n.exactMatch(key, uint8(bits)) 119 | if r == nil { 120 | return nil, false 121 | } 122 | 123 | return r.value, true 124 | } 125 | 126 | // Delete removes subtree which is contained by given key. The method uses copy on write strategy. 127 | func (n *node64s) Delete(key uint64, bits int) (*node64s, bool) { 128 | if n == nil { 129 | return n, false 130 | } 131 | 132 | if bits < 0 { 133 | bits = 0 134 | } else if bits > key64BitSize { 135 | bits = key64BitSize 136 | } 137 | 138 | return n.del(key, uint8(bits)) 139 | } 140 | 141 | func (n *node64s) dotString() string { 142 | if n == nil { 143 | return "[label=\"nil\"]" 144 | } 145 | 146 | if n.leaf { 147 | return fmt.Sprintf("[label=\"k: %016x, b: %d, v: \\\"%p\\\"\"]", n.key, n.bits, n.value) 148 | } 149 | 150 | return fmt.Sprintf("[label=\"k: %016x, b: %d\"]", n.key, n.bits) 151 | } 152 | 153 | func (n *node64s) insert(c *node64s) *node64s { 154 | if n == nil { 155 | return c 156 | } 157 | 158 | bits := uint8(bits.LeadingZeros64((n.key ^ c.key) | ^masks64[n.bits] | ^masks64[c.bits])) 159 | if bits < n.bits { 160 | branch := (n.key >> (key64BitSize - 1 - bits)) & 1 161 | if bits == c.bits { 162 | c.chld[branch] = n 163 | return c 164 | } 165 | 166 | m := newNode64s(c.key&masks64[bits], bits, false, nil) 167 | m.chld[branch] = n 168 | m.chld[1-branch] = c 169 | 170 | return m 171 | } 172 | 173 | if c.bits == n.bits { 174 | c.chld = n.chld 175 | return c 176 | } 177 | 178 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 179 | m.chld = n.chld 180 | 181 | branch := (c.key >> (key64BitSize - 1 - bits)) & 1 182 | m.chld[branch] = m.chld[branch].insert(c) 183 | 184 | return m 185 | } 186 | 187 | func (n *node64s) inplaceInsert(key uint64, sbits uint8, value *node64) *node64s { 188 | var ( 189 | p *node64s 190 | branch uint64 191 | ) 192 | 193 | r := n 194 | 195 | for n != nil { 196 | cbits := uint8(bits.LeadingZeros64((n.key ^ key) | ^masks64[n.bits] | ^masks64[sbits])) 197 | if cbits < n.bits { 198 | pBranch := branch 199 | branch = (n.key >> (key64BitSize - 1 - cbits)) & 1 200 | 201 | var m *node64s 202 | 203 | if cbits == sbits { 204 | m = newNode64s(key, sbits, true, value) 205 | m.chld[branch] = n 206 | } else { 207 | m = newNode64s(key&masks64[cbits], cbits, false, nil) 208 | m.chld[1-branch] = newNode64s(key, sbits, true, value) 209 | } 210 | 211 | m.chld[branch] = n 212 | if p == nil { 213 | r = m 214 | } else { 215 | p.chld[pBranch] = m 216 | } 217 | 218 | return r 219 | } 220 | 221 | if sbits == n.bits { 222 | n.key = key 223 | n.leaf = true 224 | n.value = value 225 | return r 226 | } 227 | 228 | p = n 229 | branch = (key >> (key64BitSize - 1 - cbits)) & 1 230 | n = n.chld[branch] 231 | } 232 | 233 | n = newNode64s(key, sbits, true, value) 234 | if p == nil { 235 | return n 236 | } 237 | 238 | p.chld[branch] = n 239 | return r 240 | } 241 | 242 | func (n *node64s) enumerate(ch chan *node64s) { 243 | if n.leaf { 244 | ch <- n 245 | } 246 | 247 | if n.chld[0] != nil { 248 | n.chld[0].enumerate(ch) 249 | } 250 | 251 | if n.chld[1] != nil { 252 | n.chld[1].enumerate(ch) 253 | } 254 | } 255 | 256 | func (n *node64s) match(key uint64, bits uint8) *node64s { 257 | if n.bits > bits { 258 | return nil 259 | } 260 | 261 | if n.bits == bits { 262 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 263 | return n 264 | } 265 | 266 | return nil 267 | } 268 | 269 | if (n.key^key)&masks64[n.bits] != 0 { 270 | return nil 271 | } 272 | 273 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 274 | if c != nil { 275 | r := c.match(key, bits) 276 | if r != nil { 277 | return r 278 | } 279 | } 280 | 281 | if n.leaf { 282 | return n 283 | } 284 | 285 | return nil 286 | } 287 | 288 | func (n *node64s) exactMatch(key uint64, bits uint8) *node64s { 289 | if n.bits > bits { 290 | return nil 291 | } 292 | 293 | if n.bits == bits { 294 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 295 | return n 296 | } 297 | 298 | return nil 299 | } 300 | 301 | if (n.key^key)&masks64[n.bits] != 0 { 302 | return nil 303 | } 304 | 305 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 306 | if c != nil { 307 | r := c.exactMatch(key, bits) 308 | if r != nil { 309 | return r 310 | } 311 | } 312 | 313 | return nil 314 | } 315 | 316 | func (n *node64s) del(key uint64, bits uint8) (*node64s, bool) { 317 | if bits <= n.bits { 318 | if (n.key^key)&masks64[bits] == 0 { 319 | return nil, true 320 | } 321 | 322 | return n, false 323 | } 324 | 325 | if (n.key^key)&masks64[n.bits] != 0 { 326 | return n, false 327 | } 328 | 329 | branch := (key >> (key64BitSize - 1 - n.bits)) & 1 330 | c := n.chld[branch] 331 | if c == nil { 332 | return n, false 333 | } 334 | 335 | c, ok := c.del(key, bits) 336 | if !ok { 337 | return n, false 338 | } 339 | 340 | if c == nil && !n.leaf { 341 | return n.chld[1-branch], true 342 | } 343 | 344 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 345 | m.chld = n.chld 346 | 347 | m.chld[branch] = c 348 | return m, true 349 | } 350 | 351 | func newNode64s(key uint64, bits uint8, leaf bool, value *node64) *node64s { 352 | return &node64s{ 353 | key: key, 354 | bits: bits, 355 | leaf: leaf, 356 | value: value} 357 | } 358 | -------------------------------------------------------------------------------- /uintX/iptree32/node64s.go: -------------------------------------------------------------------------------- 1 | package iptree32 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint32 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import ( 6 | "fmt" 7 | "math/bits" 8 | ) 9 | 10 | // node64s is an element of radix tree with 64-bit unsigned integer as a key. 11 | type node64s struct { 12 | // key stores key for current node. 13 | key uint64 14 | // bits is a number of significant bits in key. 15 | bits uint8 16 | // leaf indicates if the node is leaf node and contains any data in value. 17 | leaf bool 18 | // value contains data associated with key. 19 | value *node64 20 | 21 | chld [2]*node64s 22 | } 23 | 24 | // Dot dumps tree to Graphviz .dot format 25 | func (n *node64s) Dot() string { 26 | body := "" 27 | 28 | i := 0 29 | queue := []*node64s{n} 30 | for len(queue) > 0 { 31 | c := queue[0] 32 | body += fmt.Sprintf("N%d %s\n", i, c.dotString()) 33 | 34 | if c != nil && (c.chld[0] != nil || c.chld[1] != nil) { 35 | body += fmt.Sprintf("N%d -> { N%d N%d }\n", i, i+len(queue), i+len(queue)+1) 36 | queue = append(append(queue, c.chld[0]), c.chld[1]) 37 | } 38 | 39 | queue = queue[1:] 40 | i++ 41 | } 42 | 43 | return "digraph d {\n" + body + "}\n" 44 | } 45 | 46 | // Insert puts new leaf to radix tree and returns pointer to new root. The method uses copy on write strategy so old root doesn't see the change. 47 | func (n *node64s) Insert(key uint64, bits int, value *node64) *node64s { 48 | if bits < 0 { 49 | bits = 0 50 | } else if bits > key64BitSize { 51 | bits = key64BitSize 52 | } 53 | 54 | return n.insert(newNode64s(key, uint8(bits), true, value)) 55 | } 56 | 57 | // InplaceInsert puts new leaf to radix tree (or replaces value in existing one). The method inserts data directly to current tree so make sure you have exclusive access to it. 58 | func (n *node64s) InplaceInsert(key uint64, bits int, value *node64) *node64s { 59 | // Adjust bits. 60 | if bits < 0 { 61 | bits = 0 62 | } else if bits > key64BitSize { 63 | bits = key64BitSize 64 | } 65 | 66 | return n.inplaceInsert(key, uint8(bits), value) 67 | } 68 | 69 | // Enumerate returns channel which is populated by nodes in order of their keys. 70 | func (n *node64s) Enumerate() chan *node64s { 71 | ch := make(chan *node64s) 72 | 73 | go func() { 74 | defer close(ch) 75 | 76 | if n == nil { 77 | return 78 | } 79 | 80 | n.enumerate(ch) 81 | }() 82 | 83 | return ch 84 | } 85 | 86 | // Match locates node which key is equal to or "contains" the key passed as argument. 87 | func (n *node64s) Match(key uint64, bits int) (*node64, bool) { 88 | if n == nil { 89 | return nil, false 90 | } 91 | 92 | if bits < 0 { 93 | bits = 0 94 | } else if bits > key64BitSize { 95 | bits = key64BitSize 96 | } 97 | 98 | r := n.match(key, uint8(bits)) 99 | if r == nil { 100 | return nil, false 101 | } 102 | 103 | return r.value, true 104 | } 105 | 106 | // ExactMatch locates node which exactly matches given key. 107 | func (n *node64s) ExactMatch(key uint64, bits int) (*node64, bool) { 108 | if n == nil { 109 | return nil, false 110 | } 111 | 112 | if bits < 0 { 113 | bits = 0 114 | } else if bits > key64BitSize { 115 | bits = key64BitSize 116 | } 117 | 118 | r := n.exactMatch(key, uint8(bits)) 119 | if r == nil { 120 | return nil, false 121 | } 122 | 123 | return r.value, true 124 | } 125 | 126 | // Delete removes subtree which is contained by given key. The method uses copy on write strategy. 127 | func (n *node64s) Delete(key uint64, bits int) (*node64s, bool) { 128 | if n == nil { 129 | return n, false 130 | } 131 | 132 | if bits < 0 { 133 | bits = 0 134 | } else if bits > key64BitSize { 135 | bits = key64BitSize 136 | } 137 | 138 | return n.del(key, uint8(bits)) 139 | } 140 | 141 | func (n *node64s) dotString() string { 142 | if n == nil { 143 | return "[label=\"nil\"]" 144 | } 145 | 146 | if n.leaf { 147 | return fmt.Sprintf("[label=\"k: %016x, b: %d, v: \\\"%p\\\"\"]", n.key, n.bits, n.value) 148 | } 149 | 150 | return fmt.Sprintf("[label=\"k: %016x, b: %d\"]", n.key, n.bits) 151 | } 152 | 153 | func (n *node64s) insert(c *node64s) *node64s { 154 | if n == nil { 155 | return c 156 | } 157 | 158 | bits := uint8(bits.LeadingZeros64((n.key ^ c.key) | ^masks64[n.bits] | ^masks64[c.bits])) 159 | if bits < n.bits { 160 | branch := (n.key >> (key64BitSize - 1 - bits)) & 1 161 | if bits == c.bits { 162 | c.chld[branch] = n 163 | return c 164 | } 165 | 166 | m := newNode64s(c.key&masks64[bits], bits, false, nil) 167 | m.chld[branch] = n 168 | m.chld[1-branch] = c 169 | 170 | return m 171 | } 172 | 173 | if c.bits == n.bits { 174 | c.chld = n.chld 175 | return c 176 | } 177 | 178 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 179 | m.chld = n.chld 180 | 181 | branch := (c.key >> (key64BitSize - 1 - bits)) & 1 182 | m.chld[branch] = m.chld[branch].insert(c) 183 | 184 | return m 185 | } 186 | 187 | func (n *node64s) inplaceInsert(key uint64, sbits uint8, value *node64) *node64s { 188 | var ( 189 | p *node64s 190 | branch uint64 191 | ) 192 | 193 | r := n 194 | 195 | for n != nil { 196 | cbits := uint8(bits.LeadingZeros64((n.key ^ key) | ^masks64[n.bits] | ^masks64[sbits])) 197 | if cbits < n.bits { 198 | pBranch := branch 199 | branch = (n.key >> (key64BitSize - 1 - cbits)) & 1 200 | 201 | var m *node64s 202 | 203 | if cbits == sbits { 204 | m = newNode64s(key, sbits, true, value) 205 | m.chld[branch] = n 206 | } else { 207 | m = newNode64s(key&masks64[cbits], cbits, false, nil) 208 | m.chld[1-branch] = newNode64s(key, sbits, true, value) 209 | } 210 | 211 | m.chld[branch] = n 212 | if p == nil { 213 | r = m 214 | } else { 215 | p.chld[pBranch] = m 216 | } 217 | 218 | return r 219 | } 220 | 221 | if sbits == n.bits { 222 | n.key = key 223 | n.leaf = true 224 | n.value = value 225 | return r 226 | } 227 | 228 | p = n 229 | branch = (key >> (key64BitSize - 1 - cbits)) & 1 230 | n = n.chld[branch] 231 | } 232 | 233 | n = newNode64s(key, sbits, true, value) 234 | if p == nil { 235 | return n 236 | } 237 | 238 | p.chld[branch] = n 239 | return r 240 | } 241 | 242 | func (n *node64s) enumerate(ch chan *node64s) { 243 | if n.leaf { 244 | ch <- n 245 | } 246 | 247 | if n.chld[0] != nil { 248 | n.chld[0].enumerate(ch) 249 | } 250 | 251 | if n.chld[1] != nil { 252 | n.chld[1].enumerate(ch) 253 | } 254 | } 255 | 256 | func (n *node64s) match(key uint64, bits uint8) *node64s { 257 | if n.bits > bits { 258 | return nil 259 | } 260 | 261 | if n.bits == bits { 262 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 263 | return n 264 | } 265 | 266 | return nil 267 | } 268 | 269 | if (n.key^key)&masks64[n.bits] != 0 { 270 | return nil 271 | } 272 | 273 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 274 | if c != nil { 275 | r := c.match(key, bits) 276 | if r != nil { 277 | return r 278 | } 279 | } 280 | 281 | if n.leaf { 282 | return n 283 | } 284 | 285 | return nil 286 | } 287 | 288 | func (n *node64s) exactMatch(key uint64, bits uint8) *node64s { 289 | if n.bits > bits { 290 | return nil 291 | } 292 | 293 | if n.bits == bits { 294 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 295 | return n 296 | } 297 | 298 | return nil 299 | } 300 | 301 | if (n.key^key)&masks64[n.bits] != 0 { 302 | return nil 303 | } 304 | 305 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 306 | if c != nil { 307 | r := c.exactMatch(key, bits) 308 | if r != nil { 309 | return r 310 | } 311 | } 312 | 313 | return nil 314 | } 315 | 316 | func (n *node64s) del(key uint64, bits uint8) (*node64s, bool) { 317 | if bits <= n.bits { 318 | if (n.key^key)&masks64[bits] == 0 { 319 | return nil, true 320 | } 321 | 322 | return n, false 323 | } 324 | 325 | if (n.key^key)&masks64[n.bits] != 0 { 326 | return n, false 327 | } 328 | 329 | branch := (key >> (key64BitSize - 1 - n.bits)) & 1 330 | c := n.chld[branch] 331 | if c == nil { 332 | return n, false 333 | } 334 | 335 | c, ok := c.del(key, bits) 336 | if !ok { 337 | return n, false 338 | } 339 | 340 | if c == nil && !n.leaf { 341 | return n.chld[1-branch], true 342 | } 343 | 344 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 345 | m.chld = n.chld 346 | 347 | m.chld[branch] = c 348 | return m, true 349 | } 350 | 351 | func newNode64s(key uint64, bits uint8, leaf bool, value *node64) *node64s { 352 | return &node64s{ 353 | key: key, 354 | bits: bits, 355 | leaf: leaf, 356 | value: value} 357 | } 358 | -------------------------------------------------------------------------------- /uintX/iptree64/node64s.go: -------------------------------------------------------------------------------- 1 | package iptree64 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint64 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import ( 6 | "fmt" 7 | "math/bits" 8 | ) 9 | 10 | // node64s is an element of radix tree with 64-bit unsigned integer as a key. 11 | type node64s struct { 12 | // key stores key for current node. 13 | key uint64 14 | // bits is a number of significant bits in key. 15 | bits uint8 16 | // leaf indicates if the node is leaf node and contains any data in value. 17 | leaf bool 18 | // value contains data associated with key. 19 | value *node64 20 | 21 | chld [2]*node64s 22 | } 23 | 24 | // Dot dumps tree to Graphviz .dot format 25 | func (n *node64s) Dot() string { 26 | body := "" 27 | 28 | i := 0 29 | queue := []*node64s{n} 30 | for len(queue) > 0 { 31 | c := queue[0] 32 | body += fmt.Sprintf("N%d %s\n", i, c.dotString()) 33 | 34 | if c != nil && (c.chld[0] != nil || c.chld[1] != nil) { 35 | body += fmt.Sprintf("N%d -> { N%d N%d }\n", i, i+len(queue), i+len(queue)+1) 36 | queue = append(append(queue, c.chld[0]), c.chld[1]) 37 | } 38 | 39 | queue = queue[1:] 40 | i++ 41 | } 42 | 43 | return "digraph d {\n" + body + "}\n" 44 | } 45 | 46 | // Insert puts new leaf to radix tree and returns pointer to new root. The method uses copy on write strategy so old root doesn't see the change. 47 | func (n *node64s) Insert(key uint64, bits int, value *node64) *node64s { 48 | if bits < 0 { 49 | bits = 0 50 | } else if bits > key64BitSize { 51 | bits = key64BitSize 52 | } 53 | 54 | return n.insert(newNode64s(key, uint8(bits), true, value)) 55 | } 56 | 57 | // InplaceInsert puts new leaf to radix tree (or replaces value in existing one). The method inserts data directly to current tree so make sure you have exclusive access to it. 58 | func (n *node64s) InplaceInsert(key uint64, bits int, value *node64) *node64s { 59 | // Adjust bits. 60 | if bits < 0 { 61 | bits = 0 62 | } else if bits > key64BitSize { 63 | bits = key64BitSize 64 | } 65 | 66 | return n.inplaceInsert(key, uint8(bits), value) 67 | } 68 | 69 | // Enumerate returns channel which is populated by nodes in order of their keys. 70 | func (n *node64s) Enumerate() chan *node64s { 71 | ch := make(chan *node64s) 72 | 73 | go func() { 74 | defer close(ch) 75 | 76 | if n == nil { 77 | return 78 | } 79 | 80 | n.enumerate(ch) 81 | }() 82 | 83 | return ch 84 | } 85 | 86 | // Match locates node which key is equal to or "contains" the key passed as argument. 87 | func (n *node64s) Match(key uint64, bits int) (*node64, bool) { 88 | if n == nil { 89 | return nil, false 90 | } 91 | 92 | if bits < 0 { 93 | bits = 0 94 | } else if bits > key64BitSize { 95 | bits = key64BitSize 96 | } 97 | 98 | r := n.match(key, uint8(bits)) 99 | if r == nil { 100 | return nil, false 101 | } 102 | 103 | return r.value, true 104 | } 105 | 106 | // ExactMatch locates node which exactly matches given key. 107 | func (n *node64s) ExactMatch(key uint64, bits int) (*node64, bool) { 108 | if n == nil { 109 | return nil, false 110 | } 111 | 112 | if bits < 0 { 113 | bits = 0 114 | } else if bits > key64BitSize { 115 | bits = key64BitSize 116 | } 117 | 118 | r := n.exactMatch(key, uint8(bits)) 119 | if r == nil { 120 | return nil, false 121 | } 122 | 123 | return r.value, true 124 | } 125 | 126 | // Delete removes subtree which is contained by given key. The method uses copy on write strategy. 127 | func (n *node64s) Delete(key uint64, bits int) (*node64s, bool) { 128 | if n == nil { 129 | return n, false 130 | } 131 | 132 | if bits < 0 { 133 | bits = 0 134 | } else if bits > key64BitSize { 135 | bits = key64BitSize 136 | } 137 | 138 | return n.del(key, uint8(bits)) 139 | } 140 | 141 | func (n *node64s) dotString() string { 142 | if n == nil { 143 | return "[label=\"nil\"]" 144 | } 145 | 146 | if n.leaf { 147 | return fmt.Sprintf("[label=\"k: %016x, b: %d, v: \\\"%p\\\"\"]", n.key, n.bits, n.value) 148 | } 149 | 150 | return fmt.Sprintf("[label=\"k: %016x, b: %d\"]", n.key, n.bits) 151 | } 152 | 153 | func (n *node64s) insert(c *node64s) *node64s { 154 | if n == nil { 155 | return c 156 | } 157 | 158 | bits := uint8(bits.LeadingZeros64((n.key ^ c.key) | ^masks64[n.bits] | ^masks64[c.bits])) 159 | if bits < n.bits { 160 | branch := (n.key >> (key64BitSize - 1 - bits)) & 1 161 | if bits == c.bits { 162 | c.chld[branch] = n 163 | return c 164 | } 165 | 166 | m := newNode64s(c.key&masks64[bits], bits, false, nil) 167 | m.chld[branch] = n 168 | m.chld[1-branch] = c 169 | 170 | return m 171 | } 172 | 173 | if c.bits == n.bits { 174 | c.chld = n.chld 175 | return c 176 | } 177 | 178 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 179 | m.chld = n.chld 180 | 181 | branch := (c.key >> (key64BitSize - 1 - bits)) & 1 182 | m.chld[branch] = m.chld[branch].insert(c) 183 | 184 | return m 185 | } 186 | 187 | func (n *node64s) inplaceInsert(key uint64, sbits uint8, value *node64) *node64s { 188 | var ( 189 | p *node64s 190 | branch uint64 191 | ) 192 | 193 | r := n 194 | 195 | for n != nil { 196 | cbits := uint8(bits.LeadingZeros64((n.key ^ key) | ^masks64[n.bits] | ^masks64[sbits])) 197 | if cbits < n.bits { 198 | pBranch := branch 199 | branch = (n.key >> (key64BitSize - 1 - cbits)) & 1 200 | 201 | var m *node64s 202 | 203 | if cbits == sbits { 204 | m = newNode64s(key, sbits, true, value) 205 | m.chld[branch] = n 206 | } else { 207 | m = newNode64s(key&masks64[cbits], cbits, false, nil) 208 | m.chld[1-branch] = newNode64s(key, sbits, true, value) 209 | } 210 | 211 | m.chld[branch] = n 212 | if p == nil { 213 | r = m 214 | } else { 215 | p.chld[pBranch] = m 216 | } 217 | 218 | return r 219 | } 220 | 221 | if sbits == n.bits { 222 | n.key = key 223 | n.leaf = true 224 | n.value = value 225 | return r 226 | } 227 | 228 | p = n 229 | branch = (key >> (key64BitSize - 1 - cbits)) & 1 230 | n = n.chld[branch] 231 | } 232 | 233 | n = newNode64s(key, sbits, true, value) 234 | if p == nil { 235 | return n 236 | } 237 | 238 | p.chld[branch] = n 239 | return r 240 | } 241 | 242 | func (n *node64s) enumerate(ch chan *node64s) { 243 | if n.leaf { 244 | ch <- n 245 | } 246 | 247 | if n.chld[0] != nil { 248 | n.chld[0].enumerate(ch) 249 | } 250 | 251 | if n.chld[1] != nil { 252 | n.chld[1].enumerate(ch) 253 | } 254 | } 255 | 256 | func (n *node64s) match(key uint64, bits uint8) *node64s { 257 | if n.bits > bits { 258 | return nil 259 | } 260 | 261 | if n.bits == bits { 262 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 263 | return n 264 | } 265 | 266 | return nil 267 | } 268 | 269 | if (n.key^key)&masks64[n.bits] != 0 { 270 | return nil 271 | } 272 | 273 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 274 | if c != nil { 275 | r := c.match(key, bits) 276 | if r != nil { 277 | return r 278 | } 279 | } 280 | 281 | if n.leaf { 282 | return n 283 | } 284 | 285 | return nil 286 | } 287 | 288 | func (n *node64s) exactMatch(key uint64, bits uint8) *node64s { 289 | if n.bits > bits { 290 | return nil 291 | } 292 | 293 | if n.bits == bits { 294 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 295 | return n 296 | } 297 | 298 | return nil 299 | } 300 | 301 | if (n.key^key)&masks64[n.bits] != 0 { 302 | return nil 303 | } 304 | 305 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 306 | if c != nil { 307 | r := c.exactMatch(key, bits) 308 | if r != nil { 309 | return r 310 | } 311 | } 312 | 313 | return nil 314 | } 315 | 316 | func (n *node64s) del(key uint64, bits uint8) (*node64s, bool) { 317 | if bits <= n.bits { 318 | if (n.key^key)&masks64[bits] == 0 { 319 | return nil, true 320 | } 321 | 322 | return n, false 323 | } 324 | 325 | if (n.key^key)&masks64[n.bits] != 0 { 326 | return n, false 327 | } 328 | 329 | branch := (key >> (key64BitSize - 1 - n.bits)) & 1 330 | c := n.chld[branch] 331 | if c == nil { 332 | return n, false 333 | } 334 | 335 | c, ok := c.del(key, bits) 336 | if !ok { 337 | return n, false 338 | } 339 | 340 | if c == nil && !n.leaf { 341 | return n.chld[1-branch], true 342 | } 343 | 344 | m := newNode64s(n.key, n.bits, n.leaf, n.value) 345 | m.chld = n.chld 346 | 347 | m.chld[branch] = c 348 | return m, true 349 | } 350 | 351 | func newNode64s(key uint64, bits uint8, leaf bool, value *node64) *node64s { 352 | return &node64s{ 353 | key: key, 354 | bits: bits, 355 | leaf: leaf, 356 | value: value} 357 | } 358 | -------------------------------------------------------------------------------- /domain/name_test.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "strings" 7 | "testing" 8 | ) 9 | 10 | func TestNameMakeNameFromString(t *testing.T) { 11 | s := "wiki.example.com" 12 | n, err := MakeNameFromString(s) 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | 17 | if n.h != s { 18 | t.Errorf("expected %q as human-readable name but got %q", s, n.h) 19 | } 20 | 21 | e := "\x03COM\x07EXAMPLE\x04WIKI" 22 | if n.c != e { 23 | t.Errorf("expected %q as name for comparison but got %q", e, n.c) 24 | } 25 | } 26 | 27 | func TestNameMakeNameFromStringEmpty(t *testing.T) { 28 | s := "" 29 | n, err := MakeNameFromString(s) 30 | if err != nil { 31 | t.Fatal(err) 32 | } 33 | 34 | if n.h != s { 35 | t.Errorf("expected %q as human-readable name but got %q", s, n.h) 36 | } 37 | 38 | e := "" 39 | if n.c != e { 40 | t.Errorf("expected %q as name for comparison but got %q", e, n.c) 41 | } 42 | } 43 | 44 | func TestNameMakeNameFromStringDot(t *testing.T) { 45 | s := "." 46 | n, err := MakeNameFromString(s) 47 | if err != nil { 48 | t.Fatal(err) 49 | } 50 | 51 | if n.h != s { 52 | t.Errorf("expected %q as human-readable name but got %q", s, n.h) 53 | } 54 | 55 | e := "" 56 | if n.c != e { 57 | t.Errorf("expected %q as name for comparison but got %q", e, n.c) 58 | } 59 | } 60 | 61 | func TestNameMakeNameFromStringWithNameTooLong(t *testing.T) { 62 | s := "toooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo." + 63 | "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong." + 64 | "doooooooooooooooooooooooooooooooooooooooooooooooooooooooooomain." + 65 | "naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaame" 66 | 67 | n, err := MakeNameFromString(s) 68 | if err == nil { 69 | t.Fatalf("expected error but got name %q", n.c) 70 | } 71 | 72 | if err != ErrNameTooLong { 73 | t.Fatalf("expected ErrNameTooLong but got %q (%T)", err, err) 74 | } 75 | } 76 | 77 | func TestNameMakeNameFromStringWithTooManyLabels(t *testing.T) { 78 | s := "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." + 79 | "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." + 80 | "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." + 81 | "0.1.2.3.4.5.6.7" 82 | 83 | n, err := MakeNameFromString(s) 84 | if err == nil { 85 | t.Fatalf("expected error but got name %q", n.c) 86 | } 87 | 88 | if err != ErrTooManyLabels { 89 | t.Fatalf("expected ErrTooManyLabels but got %q (%T)", err, err) 90 | } 91 | } 92 | 93 | func TestNameMakeNameFromStringWithTooLongLabel(t *testing.T) { 94 | s := "www.looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong.com" 95 | 96 | n, err := MakeNameFromString(s) 97 | if err == nil { 98 | t.Fatalf("expected error but got name %q", n.c) 99 | } 100 | 101 | if err != ErrLabelTooLong { 102 | t.Fatalf("expected ErrLabelTooLong but got %q (%T)", err, err) 103 | } 104 | } 105 | 106 | func TestNameMakeNameFromReflection(t *testing.T) { 107 | n, err := MakeNameFromString("www.example.com") 108 | if err != nil { 109 | t.Fatal(err) 110 | } 111 | 112 | nr := MakeNameFromReflection(reflect.ValueOf(n)) 113 | if nr.h != n.h || nr.c != n.c { 114 | t.Errorf("expected %q (%q) but got %q (%q)", n, n.c, nr, nr.c) 115 | } 116 | 117 | nr = MakeNameFromReflection(reflect.ValueOf("www.example.com")) 118 | if nr.String() != "www.example.com" { 119 | t.Errorf("expected %q but got %q", "www.example.com", nr) 120 | } 121 | } 122 | 123 | func TestNameMakeNameFromReflectionPtr(t *testing.T) { 124 | n, err := MakeNameFromString("www.example.com") 125 | if err != nil { 126 | t.Fatal(err) 127 | } 128 | 129 | nr := MakeNameFromReflection(reflect.ValueOf(&n)) 130 | if nr.h != n.h || nr.c != n.c { 131 | t.Errorf("expected %q (%q) but got %q (%q)", n, n.c, nr, nr.c) 132 | } 133 | } 134 | 135 | func TestNameMakeNameFromReflectionPanicWrongType(t *testing.T) { 136 | var ( 137 | i int 138 | n Name 139 | ) 140 | 141 | defer func() { 142 | if r := recover(); r != nil { 143 | if err, ok := r.(error); ok { 144 | name := reflect.TypeOf(i).Name() 145 | if !strings.Contains(err.Error(), name) { 146 | t.Errorf("expected %q in error message but got %s", name, err) 147 | } 148 | } else { 149 | t.Errorf("expected panic on error but got %T (%#v)", r, r) 150 | } 151 | } else { 152 | t.Fatalf("expected panic but got name %q", n) 153 | } 154 | }() 155 | 156 | n = MakeNameFromReflection(reflect.ValueOf(&i)) 157 | } 158 | 159 | func TestNameMakeNameFromReflectionPanicWrongString(t *testing.T) { 160 | s := "empty..label" 161 | var n Name 162 | 163 | defer func() { 164 | if r := recover(); r != nil { 165 | if err, ok := r.(error); ok { 166 | if !strings.Contains(err.Error(), s) { 167 | t.Errorf("expected %q in error message but got %s", s, err) 168 | } 169 | } else { 170 | t.Errorf("expected panic on error but got %T (%#v)", r, r) 171 | } 172 | } else { 173 | t.Fatalf("expected panic but got name %q", n) 174 | } 175 | }() 176 | 177 | n = MakeNameFromReflection(reflect.ValueOf(s)) 178 | } 179 | 180 | func TestNameString(t *testing.T) { 181 | s := "wiki.example.com" 182 | n, err := MakeNameFromString(s) 183 | if err != nil { 184 | t.Fatal(err) 185 | } 186 | 187 | h := n.String() 188 | if h != s { 189 | t.Errorf("expected %q as human-readable name but got %q", s, n.h) 190 | } 191 | } 192 | 193 | func TestGetLabel(t *testing.T) { 194 | s := "wiki.example.com" 195 | n, err := MakeNameFromString(s) 196 | if err != nil { 197 | t.Fatal(err) 198 | } 199 | 200 | lbls := []string{} 201 | off := 0 202 | for { 203 | lbl, next := n.GetLabel(off) 204 | if next < 0 { 205 | t.Fatalf("expected nonnegative offset but got %d after %d (%#v)", next, off, lbls) 206 | } 207 | 208 | lbls = append(lbls, lbl) 209 | off = next 210 | if off == 0 { 211 | break 212 | } 213 | } 214 | 215 | assertLabels(t, lbls, []string{"COM", "EXAMPLE", "WIKI"}) 216 | } 217 | 218 | func TestGetLabelWithRoot(t *testing.T) { 219 | s := "" 220 | n, err := MakeNameFromString(s) 221 | if err != nil { 222 | t.Fatal(err) 223 | } 224 | 225 | lbls := []string{} 226 | off := 0 227 | for { 228 | lbl, next := n.GetLabel(off) 229 | if next < 0 { 230 | t.Fatalf("expected nonnegative offset but got %d after %d (%#v)", next, off, lbls) 231 | } 232 | 233 | lbls = append(lbls, lbl) 234 | off = next 235 | if off == 0 { 236 | break 237 | } 238 | } 239 | 240 | assertLabels(t, lbls, []string{""}) 241 | } 242 | 243 | func TestGetLabelWithInvalidOffset(t *testing.T) { 244 | s := "wiki.example.com" 245 | n, err := MakeNameFromString(s) 246 | if err != nil { 247 | t.Fatal(err) 248 | } 249 | 250 | lbl, off := n.GetLabel(-1) 251 | if off >= 0 { 252 | t.Errorf("expected negative offset but got label %q", lbl) 253 | } 254 | 255 | lbl, off = n.GetLabel(len(n.c)) 256 | if off >= 0 { 257 | t.Errorf("expected negative offset but got label %q", lbl) 258 | } 259 | 260 | lbl, off = n.GetLabel(2) 261 | if off >= 0 { 262 | t.Errorf("expected negative offset but got label %q", lbl) 263 | } 264 | } 265 | 266 | func TestGetLabels(t *testing.T) { 267 | s := "wiki.example.com" 268 | n, err := MakeNameFromString(s) 269 | if err != nil { 270 | t.Fatal(err) 271 | } 272 | 273 | lbls := []string{} 274 | if err := n.GetLabels(func(lbl string) error { 275 | lbls = append(lbls, lbl) 276 | return nil 277 | }); err != nil { 278 | t.Fatal(err) 279 | } 280 | 281 | assertLabels(t, lbls, []string{"COM", "EXAMPLE", "WIKI"}) 282 | } 283 | 284 | func TestGetLabelsWithError(t *testing.T) { 285 | s := "wiki.example.com" 286 | n, err := MakeNameFromString(s) 287 | if err != nil { 288 | t.Fatal(err) 289 | } 290 | 291 | stop := fmt.Errorf("stop iteration") 292 | 293 | lbls := []string{} 294 | err = n.GetLabels(func(lbl string) error { 295 | lbls = append(lbls, lbl) 296 | if len(lbls) >= 2 { 297 | return stop 298 | } 299 | 300 | return nil 301 | }) 302 | if err == nil { 303 | t.Fatalf("expected error but got %d labels:\n%#v", len(lbls), lbls) 304 | } 305 | 306 | if err != stop { 307 | t.Errorf("expected \"stop\" error but got %q (%T)", err, err) 308 | } 309 | 310 | assertLabels(t, lbls, []string{"COM", "EXAMPLE"}) 311 | } 312 | 313 | func assertLabels(t *testing.T, v, e []string) { 314 | if len(v) != len(e) { 315 | t.Errorf("expected %d labels\n\t%#v\nbut got %d\n\t%#v", len(e), e, len(v), v) 316 | return 317 | } 318 | 319 | for i, b := range e { 320 | if v[i] != b { 321 | t.Errorf("expected labels\n\t%#v\nbut got\n\t%#v", e, v) 322 | return 323 | } 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /uintX/iptree{{.bits}}/node64.{{.ext}}: -------------------------------------------------------------------------------- 1 | package iptree{{.bits}} 2 | 3 | // {{.warning}} 4 | 5 | import ( 6 | "fmt" 7 | "math/bits" 8 | ) 9 | 10 | // key64BitSize is an alias for bitsize of 64-bit radix tree's key. 11 | const key64BitSize = 64 12 | 13 | var ( 14 | masks64 = []uint64{ 15 | 0x0000000000000000, 0x8000000000000000, 0xc000000000000000, 0xe000000000000000, 16 | 0xf000000000000000, 0xf800000000000000, 0xfc00000000000000, 0xfe00000000000000, 17 | 0xff00000000000000, 0xff80000000000000, 0xffc0000000000000, 0xffe0000000000000, 18 | 0xfff0000000000000, 0xfff8000000000000, 0xfffc000000000000, 0xfffe000000000000, 19 | 0xffff000000000000, 0xffff800000000000, 0xffffc00000000000, 0xffffe00000000000, 20 | 0xfffff00000000000, 0xfffff80000000000, 0xfffffc0000000000, 0xfffffe0000000000, 21 | 0xffffff0000000000, 0xffffff8000000000, 0xffffffc000000000, 0xffffffe000000000, 22 | 0xfffffff000000000, 0xfffffff800000000, 0xfffffffc00000000, 0xfffffffe00000000, 23 | 0xffffffff00000000, 0xffffffff80000000, 0xffffffffc0000000, 0xffffffffe0000000, 24 | 0xfffffffff0000000, 0xfffffffff8000000, 0xfffffffffc000000, 0xfffffffffe000000, 25 | 0xffffffffff000000, 0xffffffffff800000, 0xffffffffffc00000, 0xffffffffffe00000, 26 | 0xfffffffffff00000, 0xfffffffffff80000, 0xfffffffffffc0000, 0xfffffffffffe0000, 27 | 0xffffffffffff0000, 0xffffffffffff8000, 0xffffffffffffc000, 0xffffffffffffe000, 28 | 0xfffffffffffff000, 0xfffffffffffff800, 0xfffffffffffffc00, 0xfffffffffffffe00, 29 | 0xffffffffffffff00, 0xffffffffffffff80, 0xffffffffffffffc0, 0xffffffffffffffe0, 30 | 0xfffffffffffffff0, 0xfffffffffffffff8, 0xfffffffffffffffc, 0xfffffffffffffffe, 31 | 0xffffffffffffffff} 32 | ) 33 | 34 | // node64 is an element of radix tree with 64-bit unsigned integer as a key. 35 | type node64 struct { 36 | // key stores key for current node. 37 | key uint64 38 | // bits is a number of significant bits in key. 39 | bits uint8 40 | // leaf indicates if the node is leaf node and contains any data in value. 41 | leaf bool 42 | // value contains data associated with key. 43 | value uint{{.bits}} 44 | 45 | chld [2]*node64 46 | } 47 | 48 | // Dot dumps tree to Graphviz .dot format 49 | func (n *node64) Dot() string { 50 | body := "" 51 | 52 | i := 0 53 | queue := []*node64{n} 54 | for len(queue) > 0 { 55 | c := queue[0] 56 | body += fmt.Sprintf("N%d %s\n", i, c.dotString()) 57 | 58 | if c != nil && (c.chld[0] != nil || c.chld[1] != nil) { 59 | body += fmt.Sprintf("N%d -> { N%d N%d }\n", i, i+len(queue), i+len(queue)+1) 60 | queue = append(append(queue, c.chld[0]), c.chld[1]) 61 | } 62 | 63 | queue = queue[1:] 64 | i++ 65 | } 66 | 67 | return "digraph d {\n" + body + "}\n" 68 | } 69 | 70 | // Insert puts new leaf to radix tree and returns pointer to new root. The method uses copy on write strategy so old root doesn't see the change. 71 | func (n *node64) Insert(key uint64, bits int, value uint{{.bits}}) *node64 { 72 | if bits < 0 { 73 | bits = 0 74 | } else if bits > key64BitSize { 75 | bits = key64BitSize 76 | } 77 | 78 | return n.insert(newNode64(key, uint8(bits), true, value)) 79 | } 80 | 81 | // InplaceInsert puts new leaf to radix tree (or replaces value in existing one). The method inserts data directly to current tree so make sure you have exclusive access to it. 82 | func (n *node64) InplaceInsert(key uint64, bits int, value uint{{.bits}}) *node64 { 83 | // Adjust bits. 84 | if bits < 0 { 85 | bits = 0 86 | } else if bits > key64BitSize { 87 | bits = key64BitSize 88 | } 89 | 90 | return n.inplaceInsert(key, uint8(bits), value) 91 | } 92 | 93 | // Enumerate returns channel which is populated by nodes in order of their keys. 94 | func (n *node64) Enumerate() chan *node64 { 95 | ch := make(chan *node64) 96 | 97 | go func() { 98 | defer close(ch) 99 | 100 | if n == nil { 101 | return 102 | } 103 | 104 | n.enumerate(ch) 105 | }() 106 | 107 | return ch 108 | } 109 | 110 | // Match locates node which key is equal to or "contains" the key passed as argument. 111 | func (n *node64) Match(key uint64, bits int) (uint{{.bits}}, bool) { 112 | if n == nil { 113 | return 0, false 114 | } 115 | 116 | if bits < 0 { 117 | bits = 0 118 | } else if bits > key64BitSize { 119 | bits = key64BitSize 120 | } 121 | 122 | r := n.match(key, uint8(bits)) 123 | if r == nil { 124 | return 0, false 125 | } 126 | 127 | return r.value, true 128 | } 129 | 130 | // ExactMatch locates node which exactly matches given key. 131 | func (n *node64) ExactMatch(key uint64, bits int) (uint{{.bits}}, bool) { 132 | if n == nil { 133 | return 0, false 134 | } 135 | 136 | if bits < 0 { 137 | bits = 0 138 | } else if bits > key64BitSize { 139 | bits = key64BitSize 140 | } 141 | 142 | r := n.exactMatch(key, uint8(bits)) 143 | if r == nil { 144 | return 0, false 145 | } 146 | 147 | return r.value, true 148 | } 149 | 150 | // Delete removes subtree which is contained by given key. The method uses copy on write strategy. 151 | func (n *node64) Delete(key uint64, bits int) (*node64, bool) { 152 | if n == nil { 153 | return n, false 154 | } 155 | 156 | if bits < 0 { 157 | bits = 0 158 | } else if bits > key64BitSize { 159 | bits = key64BitSize 160 | } 161 | 162 | return n.del(key, uint8(bits)) 163 | } 164 | 165 | func (n *node64) dotString() string { 166 | if n == nil { 167 | return "[label=\"nil\"]" 168 | } 169 | 170 | if n.leaf { 171 | return fmt.Sprintf("[label=\"k: %016x, b: %d, v: \\\"%d\\\"\"]", n.key, n.bits, n.value) 172 | } 173 | 174 | return fmt.Sprintf("[label=\"k: %016x, b: %d\"]", n.key, n.bits) 175 | } 176 | 177 | func (n *node64) insert(c *node64) *node64 { 178 | if n == nil { 179 | return c 180 | } 181 | 182 | bits := uint8(bits.LeadingZeros64((n.key ^ c.key) | ^masks64[n.bits] | ^masks64[c.bits])) 183 | if bits < n.bits { 184 | branch := (n.key >> (key64BitSize - 1 - bits)) & 1 185 | if bits == c.bits { 186 | c.chld[branch] = n 187 | return c 188 | } 189 | 190 | m := newNode64(c.key&masks64[bits], bits, false, 0) 191 | m.chld[branch] = n 192 | m.chld[1-branch] = c 193 | 194 | return m 195 | } 196 | 197 | if c.bits == n.bits { 198 | c.chld = n.chld 199 | return c 200 | } 201 | 202 | m := newNode64(n.key, n.bits, n.leaf, n.value) 203 | m.chld = n.chld 204 | 205 | branch := (c.key >> (key64BitSize - 1 - bits)) & 1 206 | m.chld[branch] = m.chld[branch].insert(c) 207 | 208 | return m 209 | } 210 | 211 | func (n *node64) inplaceInsert(key uint64, sbits uint8, value uint{{.bits}}) *node64 { 212 | var ( 213 | p *node64 214 | branch uint64 215 | ) 216 | 217 | r := n 218 | 219 | for n != nil { 220 | cbits := uint8(bits.LeadingZeros64((n.key ^ key) | ^masks64[n.bits] | ^masks64[sbits])) 221 | if cbits < n.bits { 222 | pBranch := branch 223 | branch = (n.key >> (key64BitSize - 1 - cbits)) & 1 224 | 225 | var m *node64 226 | 227 | if cbits == sbits { 228 | m = newNode64(key, sbits, true, value) 229 | m.chld[branch] = n 230 | } else { 231 | m = newNode64(key&masks64[cbits], cbits, false, 0) 232 | m.chld[1-branch] = newNode64(key, sbits, true, value) 233 | } 234 | 235 | m.chld[branch] = n 236 | if p == nil { 237 | r = m 238 | } else { 239 | p.chld[pBranch] = m 240 | } 241 | 242 | return r 243 | } 244 | 245 | if sbits == n.bits { 246 | n.key = key 247 | n.leaf = true 248 | n.value = value 249 | return r 250 | } 251 | 252 | p = n 253 | branch = (key >> (key64BitSize - 1 - cbits)) & 1 254 | n = n.chld[branch] 255 | } 256 | 257 | n = newNode64(key, sbits, true, value) 258 | if p == nil { 259 | return n 260 | } 261 | 262 | p.chld[branch] = n 263 | return r 264 | } 265 | 266 | func (n *node64) enumerate(ch chan *node64) { 267 | if n.leaf { 268 | ch <- n 269 | } 270 | 271 | if n.chld[0] != nil { 272 | n.chld[0].enumerate(ch) 273 | } 274 | 275 | if n.chld[1] != nil { 276 | n.chld[1].enumerate(ch) 277 | } 278 | } 279 | 280 | func (n *node64) match(key uint64, bits uint8) *node64 { 281 | if n.bits > bits { 282 | return nil 283 | } 284 | 285 | if n.bits == bits { 286 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 287 | return n 288 | } 289 | 290 | return nil 291 | } 292 | 293 | if (n.key^key)&masks64[n.bits] != 0 { 294 | return nil 295 | } 296 | 297 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 298 | if c != nil { 299 | r := c.match(key, bits) 300 | if r != nil { 301 | return r 302 | } 303 | } 304 | 305 | if n.leaf { 306 | return n 307 | } 308 | 309 | return nil 310 | } 311 | 312 | func (n *node64) exactMatch(key uint64, bits uint8) *node64 { 313 | if n.bits > bits { 314 | return nil 315 | } 316 | 317 | if n.bits == bits { 318 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 319 | return n 320 | } 321 | 322 | return nil 323 | } 324 | 325 | if (n.key^key)&masks64[n.bits] != 0 { 326 | return nil 327 | } 328 | 329 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 330 | if c != nil { 331 | r := c.exactMatch(key, bits) 332 | if r != nil { 333 | return r 334 | } 335 | } 336 | 337 | return nil 338 | } 339 | 340 | func (n *node64) del(key uint64, bits uint8) (*node64, bool) { 341 | if bits <= n.bits { 342 | if (n.key^key)&masks64[bits] == 0 { 343 | return nil, true 344 | } 345 | 346 | return n, false 347 | } 348 | 349 | if (n.key^key)&masks64[n.bits] != 0 { 350 | return n, false 351 | } 352 | 353 | branch := (key >> (key64BitSize - 1 - n.bits)) & 1 354 | c := n.chld[branch] 355 | if c == nil { 356 | return n, false 357 | } 358 | 359 | c, ok := c.del(key, bits) 360 | if !ok { 361 | return n, false 362 | } 363 | 364 | if c == nil && !n.leaf { 365 | return n.chld[1-branch], true 366 | } 367 | 368 | m := newNode64(n.key, n.bits, n.leaf, n.value) 369 | m.chld = n.chld 370 | 371 | m.chld[branch] = c 372 | return m, true 373 | } 374 | 375 | func newNode64(key uint64, bits uint8, leaf bool, value uint{{.bits}}) *node64 { 376 | return &node64{ 377 | key: key, 378 | bits: bits, 379 | leaf: leaf, 380 | value: value} 381 | } 382 | -------------------------------------------------------------------------------- /uintX/iptree8/node64.go: -------------------------------------------------------------------------------- 1 | package iptree8 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint8 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import ( 6 | "fmt" 7 | "math/bits" 8 | ) 9 | 10 | // key64BitSize is an alias for bitsize of 64-bit radix tree's key. 11 | const key64BitSize = 64 12 | 13 | var ( 14 | masks64 = []uint64{ 15 | 0x0000000000000000, 0x8000000000000000, 0xc000000000000000, 0xe000000000000000, 16 | 0xf000000000000000, 0xf800000000000000, 0xfc00000000000000, 0xfe00000000000000, 17 | 0xff00000000000000, 0xff80000000000000, 0xffc0000000000000, 0xffe0000000000000, 18 | 0xfff0000000000000, 0xfff8000000000000, 0xfffc000000000000, 0xfffe000000000000, 19 | 0xffff000000000000, 0xffff800000000000, 0xffffc00000000000, 0xffffe00000000000, 20 | 0xfffff00000000000, 0xfffff80000000000, 0xfffffc0000000000, 0xfffffe0000000000, 21 | 0xffffff0000000000, 0xffffff8000000000, 0xffffffc000000000, 0xffffffe000000000, 22 | 0xfffffff000000000, 0xfffffff800000000, 0xfffffffc00000000, 0xfffffffe00000000, 23 | 0xffffffff00000000, 0xffffffff80000000, 0xffffffffc0000000, 0xffffffffe0000000, 24 | 0xfffffffff0000000, 0xfffffffff8000000, 0xfffffffffc000000, 0xfffffffffe000000, 25 | 0xffffffffff000000, 0xffffffffff800000, 0xffffffffffc00000, 0xffffffffffe00000, 26 | 0xfffffffffff00000, 0xfffffffffff80000, 0xfffffffffffc0000, 0xfffffffffffe0000, 27 | 0xffffffffffff0000, 0xffffffffffff8000, 0xffffffffffffc000, 0xffffffffffffe000, 28 | 0xfffffffffffff000, 0xfffffffffffff800, 0xfffffffffffffc00, 0xfffffffffffffe00, 29 | 0xffffffffffffff00, 0xffffffffffffff80, 0xffffffffffffffc0, 0xffffffffffffffe0, 30 | 0xfffffffffffffff0, 0xfffffffffffffff8, 0xfffffffffffffffc, 0xfffffffffffffffe, 31 | 0xffffffffffffffff} 32 | ) 33 | 34 | // node64 is an element of radix tree with 64-bit unsigned integer as a key. 35 | type node64 struct { 36 | // key stores key for current node. 37 | key uint64 38 | // bits is a number of significant bits in key. 39 | bits uint8 40 | // leaf indicates if the node is leaf node and contains any data in value. 41 | leaf bool 42 | // value contains data associated with key. 43 | value uint8 44 | 45 | chld [2]*node64 46 | } 47 | 48 | // Dot dumps tree to Graphviz .dot format 49 | func (n *node64) Dot() string { 50 | body := "" 51 | 52 | i := 0 53 | queue := []*node64{n} 54 | for len(queue) > 0 { 55 | c := queue[0] 56 | body += fmt.Sprintf("N%d %s\n", i, c.dotString()) 57 | 58 | if c != nil && (c.chld[0] != nil || c.chld[1] != nil) { 59 | body += fmt.Sprintf("N%d -> { N%d N%d }\n", i, i+len(queue), i+len(queue)+1) 60 | queue = append(append(queue, c.chld[0]), c.chld[1]) 61 | } 62 | 63 | queue = queue[1:] 64 | i++ 65 | } 66 | 67 | return "digraph d {\n" + body + "}\n" 68 | } 69 | 70 | // Insert puts new leaf to radix tree and returns pointer to new root. The method uses copy on write strategy so old root doesn't see the change. 71 | func (n *node64) Insert(key uint64, bits int, value uint8) *node64 { 72 | if bits < 0 { 73 | bits = 0 74 | } else if bits > key64BitSize { 75 | bits = key64BitSize 76 | } 77 | 78 | return n.insert(newNode64(key, uint8(bits), true, value)) 79 | } 80 | 81 | // InplaceInsert puts new leaf to radix tree (or replaces value in existing one). The method inserts data directly to current tree so make sure you have exclusive access to it. 82 | func (n *node64) InplaceInsert(key uint64, bits int, value uint8) *node64 { 83 | // Adjust bits. 84 | if bits < 0 { 85 | bits = 0 86 | } else if bits > key64BitSize { 87 | bits = key64BitSize 88 | } 89 | 90 | return n.inplaceInsert(key, uint8(bits), value) 91 | } 92 | 93 | // Enumerate returns channel which is populated by nodes in order of their keys. 94 | func (n *node64) Enumerate() chan *node64 { 95 | ch := make(chan *node64) 96 | 97 | go func() { 98 | defer close(ch) 99 | 100 | if n == nil { 101 | return 102 | } 103 | 104 | n.enumerate(ch) 105 | }() 106 | 107 | return ch 108 | } 109 | 110 | // Match locates node which key is equal to or "contains" the key passed as argument. 111 | func (n *node64) Match(key uint64, bits int) (uint8, bool) { 112 | if n == nil { 113 | return 0, false 114 | } 115 | 116 | if bits < 0 { 117 | bits = 0 118 | } else if bits > key64BitSize { 119 | bits = key64BitSize 120 | } 121 | 122 | r := n.match(key, uint8(bits)) 123 | if r == nil { 124 | return 0, false 125 | } 126 | 127 | return r.value, true 128 | } 129 | 130 | // ExactMatch locates node which exactly matches given key. 131 | func (n *node64) ExactMatch(key uint64, bits int) (uint8, bool) { 132 | if n == nil { 133 | return 0, false 134 | } 135 | 136 | if bits < 0 { 137 | bits = 0 138 | } else if bits > key64BitSize { 139 | bits = key64BitSize 140 | } 141 | 142 | r := n.exactMatch(key, uint8(bits)) 143 | if r == nil { 144 | return 0, false 145 | } 146 | 147 | return r.value, true 148 | } 149 | 150 | // Delete removes subtree which is contained by given key. The method uses copy on write strategy. 151 | func (n *node64) Delete(key uint64, bits int) (*node64, bool) { 152 | if n == nil { 153 | return n, false 154 | } 155 | 156 | if bits < 0 { 157 | bits = 0 158 | } else if bits > key64BitSize { 159 | bits = key64BitSize 160 | } 161 | 162 | return n.del(key, uint8(bits)) 163 | } 164 | 165 | func (n *node64) dotString() string { 166 | if n == nil { 167 | return "[label=\"nil\"]" 168 | } 169 | 170 | if n.leaf { 171 | return fmt.Sprintf("[label=\"k: %016x, b: %d, v: \\\"%d\\\"\"]", n.key, n.bits, n.value) 172 | } 173 | 174 | return fmt.Sprintf("[label=\"k: %016x, b: %d\"]", n.key, n.bits) 175 | } 176 | 177 | func (n *node64) insert(c *node64) *node64 { 178 | if n == nil { 179 | return c 180 | } 181 | 182 | bits := uint8(bits.LeadingZeros64((n.key ^ c.key) | ^masks64[n.bits] | ^masks64[c.bits])) 183 | if bits < n.bits { 184 | branch := (n.key >> (key64BitSize - 1 - bits)) & 1 185 | if bits == c.bits { 186 | c.chld[branch] = n 187 | return c 188 | } 189 | 190 | m := newNode64(c.key&masks64[bits], bits, false, 0) 191 | m.chld[branch] = n 192 | m.chld[1-branch] = c 193 | 194 | return m 195 | } 196 | 197 | if c.bits == n.bits { 198 | c.chld = n.chld 199 | return c 200 | } 201 | 202 | m := newNode64(n.key, n.bits, n.leaf, n.value) 203 | m.chld = n.chld 204 | 205 | branch := (c.key >> (key64BitSize - 1 - bits)) & 1 206 | m.chld[branch] = m.chld[branch].insert(c) 207 | 208 | return m 209 | } 210 | 211 | func (n *node64) inplaceInsert(key uint64, sbits uint8, value uint8) *node64 { 212 | var ( 213 | p *node64 214 | branch uint64 215 | ) 216 | 217 | r := n 218 | 219 | for n != nil { 220 | cbits := uint8(bits.LeadingZeros64((n.key ^ key) | ^masks64[n.bits] | ^masks64[sbits])) 221 | if cbits < n.bits { 222 | pBranch := branch 223 | branch = (n.key >> (key64BitSize - 1 - cbits)) & 1 224 | 225 | var m *node64 226 | 227 | if cbits == sbits { 228 | m = newNode64(key, sbits, true, value) 229 | m.chld[branch] = n 230 | } else { 231 | m = newNode64(key&masks64[cbits], cbits, false, 0) 232 | m.chld[1-branch] = newNode64(key, sbits, true, value) 233 | } 234 | 235 | m.chld[branch] = n 236 | if p == nil { 237 | r = m 238 | } else { 239 | p.chld[pBranch] = m 240 | } 241 | 242 | return r 243 | } 244 | 245 | if sbits == n.bits { 246 | n.key = key 247 | n.leaf = true 248 | n.value = value 249 | return r 250 | } 251 | 252 | p = n 253 | branch = (key >> (key64BitSize - 1 - cbits)) & 1 254 | n = n.chld[branch] 255 | } 256 | 257 | n = newNode64(key, sbits, true, value) 258 | if p == nil { 259 | return n 260 | } 261 | 262 | p.chld[branch] = n 263 | return r 264 | } 265 | 266 | func (n *node64) enumerate(ch chan *node64) { 267 | if n.leaf { 268 | ch <- n 269 | } 270 | 271 | if n.chld[0] != nil { 272 | n.chld[0].enumerate(ch) 273 | } 274 | 275 | if n.chld[1] != nil { 276 | n.chld[1].enumerate(ch) 277 | } 278 | } 279 | 280 | func (n *node64) match(key uint64, bits uint8) *node64 { 281 | if n.bits > bits { 282 | return nil 283 | } 284 | 285 | if n.bits == bits { 286 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 287 | return n 288 | } 289 | 290 | return nil 291 | } 292 | 293 | if (n.key^key)&masks64[n.bits] != 0 { 294 | return nil 295 | } 296 | 297 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 298 | if c != nil { 299 | r := c.match(key, bits) 300 | if r != nil { 301 | return r 302 | } 303 | } 304 | 305 | if n.leaf { 306 | return n 307 | } 308 | 309 | return nil 310 | } 311 | 312 | func (n *node64) exactMatch(key uint64, bits uint8) *node64 { 313 | if n.bits > bits { 314 | return nil 315 | } 316 | 317 | if n.bits == bits { 318 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 319 | return n 320 | } 321 | 322 | return nil 323 | } 324 | 325 | if (n.key^key)&masks64[n.bits] != 0 { 326 | return nil 327 | } 328 | 329 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 330 | if c != nil { 331 | r := c.exactMatch(key, bits) 332 | if r != nil { 333 | return r 334 | } 335 | } 336 | 337 | return nil 338 | } 339 | 340 | func (n *node64) del(key uint64, bits uint8) (*node64, bool) { 341 | if bits <= n.bits { 342 | if (n.key^key)&masks64[bits] == 0 { 343 | return nil, true 344 | } 345 | 346 | return n, false 347 | } 348 | 349 | if (n.key^key)&masks64[n.bits] != 0 { 350 | return n, false 351 | } 352 | 353 | branch := (key >> (key64BitSize - 1 - n.bits)) & 1 354 | c := n.chld[branch] 355 | if c == nil { 356 | return n, false 357 | } 358 | 359 | c, ok := c.del(key, bits) 360 | if !ok { 361 | return n, false 362 | } 363 | 364 | if c == nil && !n.leaf { 365 | return n.chld[1-branch], true 366 | } 367 | 368 | m := newNode64(n.key, n.bits, n.leaf, n.value) 369 | m.chld = n.chld 370 | 371 | m.chld[branch] = c 372 | return m, true 373 | } 374 | 375 | func newNode64(key uint64, bits uint8, leaf bool, value uint8) *node64 { 376 | return &node64{ 377 | key: key, 378 | bits: bits, 379 | leaf: leaf, 380 | value: value} 381 | } 382 | -------------------------------------------------------------------------------- /uintX/iptree16/node64.go: -------------------------------------------------------------------------------- 1 | package iptree16 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint16 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import ( 6 | "fmt" 7 | "math/bits" 8 | ) 9 | 10 | // key64BitSize is an alias for bitsize of 64-bit radix tree's key. 11 | const key64BitSize = 64 12 | 13 | var ( 14 | masks64 = []uint64{ 15 | 0x0000000000000000, 0x8000000000000000, 0xc000000000000000, 0xe000000000000000, 16 | 0xf000000000000000, 0xf800000000000000, 0xfc00000000000000, 0xfe00000000000000, 17 | 0xff00000000000000, 0xff80000000000000, 0xffc0000000000000, 0xffe0000000000000, 18 | 0xfff0000000000000, 0xfff8000000000000, 0xfffc000000000000, 0xfffe000000000000, 19 | 0xffff000000000000, 0xffff800000000000, 0xffffc00000000000, 0xffffe00000000000, 20 | 0xfffff00000000000, 0xfffff80000000000, 0xfffffc0000000000, 0xfffffe0000000000, 21 | 0xffffff0000000000, 0xffffff8000000000, 0xffffffc000000000, 0xffffffe000000000, 22 | 0xfffffff000000000, 0xfffffff800000000, 0xfffffffc00000000, 0xfffffffe00000000, 23 | 0xffffffff00000000, 0xffffffff80000000, 0xffffffffc0000000, 0xffffffffe0000000, 24 | 0xfffffffff0000000, 0xfffffffff8000000, 0xfffffffffc000000, 0xfffffffffe000000, 25 | 0xffffffffff000000, 0xffffffffff800000, 0xffffffffffc00000, 0xffffffffffe00000, 26 | 0xfffffffffff00000, 0xfffffffffff80000, 0xfffffffffffc0000, 0xfffffffffffe0000, 27 | 0xffffffffffff0000, 0xffffffffffff8000, 0xffffffffffffc000, 0xffffffffffffe000, 28 | 0xfffffffffffff000, 0xfffffffffffff800, 0xfffffffffffffc00, 0xfffffffffffffe00, 29 | 0xffffffffffffff00, 0xffffffffffffff80, 0xffffffffffffffc0, 0xffffffffffffffe0, 30 | 0xfffffffffffffff0, 0xfffffffffffffff8, 0xfffffffffffffffc, 0xfffffffffffffffe, 31 | 0xffffffffffffffff} 32 | ) 33 | 34 | // node64 is an element of radix tree with 64-bit unsigned integer as a key. 35 | type node64 struct { 36 | // key stores key for current node. 37 | key uint64 38 | // bits is a number of significant bits in key. 39 | bits uint8 40 | // leaf indicates if the node is leaf node and contains any data in value. 41 | leaf bool 42 | // value contains data associated with key. 43 | value uint16 44 | 45 | chld [2]*node64 46 | } 47 | 48 | // Dot dumps tree to Graphviz .dot format 49 | func (n *node64) Dot() string { 50 | body := "" 51 | 52 | i := 0 53 | queue := []*node64{n} 54 | for len(queue) > 0 { 55 | c := queue[0] 56 | body += fmt.Sprintf("N%d %s\n", i, c.dotString()) 57 | 58 | if c != nil && (c.chld[0] != nil || c.chld[1] != nil) { 59 | body += fmt.Sprintf("N%d -> { N%d N%d }\n", i, i+len(queue), i+len(queue)+1) 60 | queue = append(append(queue, c.chld[0]), c.chld[1]) 61 | } 62 | 63 | queue = queue[1:] 64 | i++ 65 | } 66 | 67 | return "digraph d {\n" + body + "}\n" 68 | } 69 | 70 | // Insert puts new leaf to radix tree and returns pointer to new root. The method uses copy on write strategy so old root doesn't see the change. 71 | func (n *node64) Insert(key uint64, bits int, value uint16) *node64 { 72 | if bits < 0 { 73 | bits = 0 74 | } else if bits > key64BitSize { 75 | bits = key64BitSize 76 | } 77 | 78 | return n.insert(newNode64(key, uint8(bits), true, value)) 79 | } 80 | 81 | // InplaceInsert puts new leaf to radix tree (or replaces value in existing one). The method inserts data directly to current tree so make sure you have exclusive access to it. 82 | func (n *node64) InplaceInsert(key uint64, bits int, value uint16) *node64 { 83 | // Adjust bits. 84 | if bits < 0 { 85 | bits = 0 86 | } else if bits > key64BitSize { 87 | bits = key64BitSize 88 | } 89 | 90 | return n.inplaceInsert(key, uint8(bits), value) 91 | } 92 | 93 | // Enumerate returns channel which is populated by nodes in order of their keys. 94 | func (n *node64) Enumerate() chan *node64 { 95 | ch := make(chan *node64) 96 | 97 | go func() { 98 | defer close(ch) 99 | 100 | if n == nil { 101 | return 102 | } 103 | 104 | n.enumerate(ch) 105 | }() 106 | 107 | return ch 108 | } 109 | 110 | // Match locates node which key is equal to or "contains" the key passed as argument. 111 | func (n *node64) Match(key uint64, bits int) (uint16, bool) { 112 | if n == nil { 113 | return 0, false 114 | } 115 | 116 | if bits < 0 { 117 | bits = 0 118 | } else if bits > key64BitSize { 119 | bits = key64BitSize 120 | } 121 | 122 | r := n.match(key, uint8(bits)) 123 | if r == nil { 124 | return 0, false 125 | } 126 | 127 | return r.value, true 128 | } 129 | 130 | // ExactMatch locates node which exactly matches given key. 131 | func (n *node64) ExactMatch(key uint64, bits int) (uint16, bool) { 132 | if n == nil { 133 | return 0, false 134 | } 135 | 136 | if bits < 0 { 137 | bits = 0 138 | } else if bits > key64BitSize { 139 | bits = key64BitSize 140 | } 141 | 142 | r := n.exactMatch(key, uint8(bits)) 143 | if r == nil { 144 | return 0, false 145 | } 146 | 147 | return r.value, true 148 | } 149 | 150 | // Delete removes subtree which is contained by given key. The method uses copy on write strategy. 151 | func (n *node64) Delete(key uint64, bits int) (*node64, bool) { 152 | if n == nil { 153 | return n, false 154 | } 155 | 156 | if bits < 0 { 157 | bits = 0 158 | } else if bits > key64BitSize { 159 | bits = key64BitSize 160 | } 161 | 162 | return n.del(key, uint8(bits)) 163 | } 164 | 165 | func (n *node64) dotString() string { 166 | if n == nil { 167 | return "[label=\"nil\"]" 168 | } 169 | 170 | if n.leaf { 171 | return fmt.Sprintf("[label=\"k: %016x, b: %d, v: \\\"%d\\\"\"]", n.key, n.bits, n.value) 172 | } 173 | 174 | return fmt.Sprintf("[label=\"k: %016x, b: %d\"]", n.key, n.bits) 175 | } 176 | 177 | func (n *node64) insert(c *node64) *node64 { 178 | if n == nil { 179 | return c 180 | } 181 | 182 | bits := uint8(bits.LeadingZeros64((n.key ^ c.key) | ^masks64[n.bits] | ^masks64[c.bits])) 183 | if bits < n.bits { 184 | branch := (n.key >> (key64BitSize - 1 - bits)) & 1 185 | if bits == c.bits { 186 | c.chld[branch] = n 187 | return c 188 | } 189 | 190 | m := newNode64(c.key&masks64[bits], bits, false, 0) 191 | m.chld[branch] = n 192 | m.chld[1-branch] = c 193 | 194 | return m 195 | } 196 | 197 | if c.bits == n.bits { 198 | c.chld = n.chld 199 | return c 200 | } 201 | 202 | m := newNode64(n.key, n.bits, n.leaf, n.value) 203 | m.chld = n.chld 204 | 205 | branch := (c.key >> (key64BitSize - 1 - bits)) & 1 206 | m.chld[branch] = m.chld[branch].insert(c) 207 | 208 | return m 209 | } 210 | 211 | func (n *node64) inplaceInsert(key uint64, sbits uint8, value uint16) *node64 { 212 | var ( 213 | p *node64 214 | branch uint64 215 | ) 216 | 217 | r := n 218 | 219 | for n != nil { 220 | cbits := uint8(bits.LeadingZeros64((n.key ^ key) | ^masks64[n.bits] | ^masks64[sbits])) 221 | if cbits < n.bits { 222 | pBranch := branch 223 | branch = (n.key >> (key64BitSize - 1 - cbits)) & 1 224 | 225 | var m *node64 226 | 227 | if cbits == sbits { 228 | m = newNode64(key, sbits, true, value) 229 | m.chld[branch] = n 230 | } else { 231 | m = newNode64(key&masks64[cbits], cbits, false, 0) 232 | m.chld[1-branch] = newNode64(key, sbits, true, value) 233 | } 234 | 235 | m.chld[branch] = n 236 | if p == nil { 237 | r = m 238 | } else { 239 | p.chld[pBranch] = m 240 | } 241 | 242 | return r 243 | } 244 | 245 | if sbits == n.bits { 246 | n.key = key 247 | n.leaf = true 248 | n.value = value 249 | return r 250 | } 251 | 252 | p = n 253 | branch = (key >> (key64BitSize - 1 - cbits)) & 1 254 | n = n.chld[branch] 255 | } 256 | 257 | n = newNode64(key, sbits, true, value) 258 | if p == nil { 259 | return n 260 | } 261 | 262 | p.chld[branch] = n 263 | return r 264 | } 265 | 266 | func (n *node64) enumerate(ch chan *node64) { 267 | if n.leaf { 268 | ch <- n 269 | } 270 | 271 | if n.chld[0] != nil { 272 | n.chld[0].enumerate(ch) 273 | } 274 | 275 | if n.chld[1] != nil { 276 | n.chld[1].enumerate(ch) 277 | } 278 | } 279 | 280 | func (n *node64) match(key uint64, bits uint8) *node64 { 281 | if n.bits > bits { 282 | return nil 283 | } 284 | 285 | if n.bits == bits { 286 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 287 | return n 288 | } 289 | 290 | return nil 291 | } 292 | 293 | if (n.key^key)&masks64[n.bits] != 0 { 294 | return nil 295 | } 296 | 297 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 298 | if c != nil { 299 | r := c.match(key, bits) 300 | if r != nil { 301 | return r 302 | } 303 | } 304 | 305 | if n.leaf { 306 | return n 307 | } 308 | 309 | return nil 310 | } 311 | 312 | func (n *node64) exactMatch(key uint64, bits uint8) *node64 { 313 | if n.bits > bits { 314 | return nil 315 | } 316 | 317 | if n.bits == bits { 318 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 319 | return n 320 | } 321 | 322 | return nil 323 | } 324 | 325 | if (n.key^key)&masks64[n.bits] != 0 { 326 | return nil 327 | } 328 | 329 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 330 | if c != nil { 331 | r := c.exactMatch(key, bits) 332 | if r != nil { 333 | return r 334 | } 335 | } 336 | 337 | return nil 338 | } 339 | 340 | func (n *node64) del(key uint64, bits uint8) (*node64, bool) { 341 | if bits <= n.bits { 342 | if (n.key^key)&masks64[bits] == 0 { 343 | return nil, true 344 | } 345 | 346 | return n, false 347 | } 348 | 349 | if (n.key^key)&masks64[n.bits] != 0 { 350 | return n, false 351 | } 352 | 353 | branch := (key >> (key64BitSize - 1 - n.bits)) & 1 354 | c := n.chld[branch] 355 | if c == nil { 356 | return n, false 357 | } 358 | 359 | c, ok := c.del(key, bits) 360 | if !ok { 361 | return n, false 362 | } 363 | 364 | if c == nil && !n.leaf { 365 | return n.chld[1-branch], true 366 | } 367 | 368 | m := newNode64(n.key, n.bits, n.leaf, n.value) 369 | m.chld = n.chld 370 | 371 | m.chld[branch] = c 372 | return m, true 373 | } 374 | 375 | func newNode64(key uint64, bits uint8, leaf bool, value uint16) *node64 { 376 | return &node64{ 377 | key: key, 378 | bits: bits, 379 | leaf: leaf, 380 | value: value} 381 | } 382 | -------------------------------------------------------------------------------- /uintX/iptree32/node64.go: -------------------------------------------------------------------------------- 1 | package iptree32 2 | 3 | // !!!DON'T EDIT!!! Generated by infobloxopen/go-trees/etc from tree{{.bits}} with etc -s uint32 -d uintX.yaml -t ./tree\{\{.bits\}\} 4 | 5 | import ( 6 | "fmt" 7 | "math/bits" 8 | ) 9 | 10 | // key64BitSize is an alias for bitsize of 64-bit radix tree's key. 11 | const key64BitSize = 64 12 | 13 | var ( 14 | masks64 = []uint64{ 15 | 0x0000000000000000, 0x8000000000000000, 0xc000000000000000, 0xe000000000000000, 16 | 0xf000000000000000, 0xf800000000000000, 0xfc00000000000000, 0xfe00000000000000, 17 | 0xff00000000000000, 0xff80000000000000, 0xffc0000000000000, 0xffe0000000000000, 18 | 0xfff0000000000000, 0xfff8000000000000, 0xfffc000000000000, 0xfffe000000000000, 19 | 0xffff000000000000, 0xffff800000000000, 0xffffc00000000000, 0xffffe00000000000, 20 | 0xfffff00000000000, 0xfffff80000000000, 0xfffffc0000000000, 0xfffffe0000000000, 21 | 0xffffff0000000000, 0xffffff8000000000, 0xffffffc000000000, 0xffffffe000000000, 22 | 0xfffffff000000000, 0xfffffff800000000, 0xfffffffc00000000, 0xfffffffe00000000, 23 | 0xffffffff00000000, 0xffffffff80000000, 0xffffffffc0000000, 0xffffffffe0000000, 24 | 0xfffffffff0000000, 0xfffffffff8000000, 0xfffffffffc000000, 0xfffffffffe000000, 25 | 0xffffffffff000000, 0xffffffffff800000, 0xffffffffffc00000, 0xffffffffffe00000, 26 | 0xfffffffffff00000, 0xfffffffffff80000, 0xfffffffffffc0000, 0xfffffffffffe0000, 27 | 0xffffffffffff0000, 0xffffffffffff8000, 0xffffffffffffc000, 0xffffffffffffe000, 28 | 0xfffffffffffff000, 0xfffffffffffff800, 0xfffffffffffffc00, 0xfffffffffffffe00, 29 | 0xffffffffffffff00, 0xffffffffffffff80, 0xffffffffffffffc0, 0xffffffffffffffe0, 30 | 0xfffffffffffffff0, 0xfffffffffffffff8, 0xfffffffffffffffc, 0xfffffffffffffffe, 31 | 0xffffffffffffffff} 32 | ) 33 | 34 | // node64 is an element of radix tree with 64-bit unsigned integer as a key. 35 | type node64 struct { 36 | // key stores key for current node. 37 | key uint64 38 | // bits is a number of significant bits in key. 39 | bits uint8 40 | // leaf indicates if the node is leaf node and contains any data in value. 41 | leaf bool 42 | // value contains data associated with key. 43 | value uint32 44 | 45 | chld [2]*node64 46 | } 47 | 48 | // Dot dumps tree to Graphviz .dot format 49 | func (n *node64) Dot() string { 50 | body := "" 51 | 52 | i := 0 53 | queue := []*node64{n} 54 | for len(queue) > 0 { 55 | c := queue[0] 56 | body += fmt.Sprintf("N%d %s\n", i, c.dotString()) 57 | 58 | if c != nil && (c.chld[0] != nil || c.chld[1] != nil) { 59 | body += fmt.Sprintf("N%d -> { N%d N%d }\n", i, i+len(queue), i+len(queue)+1) 60 | queue = append(append(queue, c.chld[0]), c.chld[1]) 61 | } 62 | 63 | queue = queue[1:] 64 | i++ 65 | } 66 | 67 | return "digraph d {\n" + body + "}\n" 68 | } 69 | 70 | // Insert puts new leaf to radix tree and returns pointer to new root. The method uses copy on write strategy so old root doesn't see the change. 71 | func (n *node64) Insert(key uint64, bits int, value uint32) *node64 { 72 | if bits < 0 { 73 | bits = 0 74 | } else if bits > key64BitSize { 75 | bits = key64BitSize 76 | } 77 | 78 | return n.insert(newNode64(key, uint8(bits), true, value)) 79 | } 80 | 81 | // InplaceInsert puts new leaf to radix tree (or replaces value in existing one). The method inserts data directly to current tree so make sure you have exclusive access to it. 82 | func (n *node64) InplaceInsert(key uint64, bits int, value uint32) *node64 { 83 | // Adjust bits. 84 | if bits < 0 { 85 | bits = 0 86 | } else if bits > key64BitSize { 87 | bits = key64BitSize 88 | } 89 | 90 | return n.inplaceInsert(key, uint8(bits), value) 91 | } 92 | 93 | // Enumerate returns channel which is populated by nodes in order of their keys. 94 | func (n *node64) Enumerate() chan *node64 { 95 | ch := make(chan *node64) 96 | 97 | go func() { 98 | defer close(ch) 99 | 100 | if n == nil { 101 | return 102 | } 103 | 104 | n.enumerate(ch) 105 | }() 106 | 107 | return ch 108 | } 109 | 110 | // Match locates node which key is equal to or "contains" the key passed as argument. 111 | func (n *node64) Match(key uint64, bits int) (uint32, bool) { 112 | if n == nil { 113 | return 0, false 114 | } 115 | 116 | if bits < 0 { 117 | bits = 0 118 | } else if bits > key64BitSize { 119 | bits = key64BitSize 120 | } 121 | 122 | r := n.match(key, uint8(bits)) 123 | if r == nil { 124 | return 0, false 125 | } 126 | 127 | return r.value, true 128 | } 129 | 130 | // ExactMatch locates node which exactly matches given key. 131 | func (n *node64) ExactMatch(key uint64, bits int) (uint32, bool) { 132 | if n == nil { 133 | return 0, false 134 | } 135 | 136 | if bits < 0 { 137 | bits = 0 138 | } else if bits > key64BitSize { 139 | bits = key64BitSize 140 | } 141 | 142 | r := n.exactMatch(key, uint8(bits)) 143 | if r == nil { 144 | return 0, false 145 | } 146 | 147 | return r.value, true 148 | } 149 | 150 | // Delete removes subtree which is contained by given key. The method uses copy on write strategy. 151 | func (n *node64) Delete(key uint64, bits int) (*node64, bool) { 152 | if n == nil { 153 | return n, false 154 | } 155 | 156 | if bits < 0 { 157 | bits = 0 158 | } else if bits > key64BitSize { 159 | bits = key64BitSize 160 | } 161 | 162 | return n.del(key, uint8(bits)) 163 | } 164 | 165 | func (n *node64) dotString() string { 166 | if n == nil { 167 | return "[label=\"nil\"]" 168 | } 169 | 170 | if n.leaf { 171 | return fmt.Sprintf("[label=\"k: %016x, b: %d, v: \\\"%d\\\"\"]", n.key, n.bits, n.value) 172 | } 173 | 174 | return fmt.Sprintf("[label=\"k: %016x, b: %d\"]", n.key, n.bits) 175 | } 176 | 177 | func (n *node64) insert(c *node64) *node64 { 178 | if n == nil { 179 | return c 180 | } 181 | 182 | bits := uint8(bits.LeadingZeros64((n.key ^ c.key) | ^masks64[n.bits] | ^masks64[c.bits])) 183 | if bits < n.bits { 184 | branch := (n.key >> (key64BitSize - 1 - bits)) & 1 185 | if bits == c.bits { 186 | c.chld[branch] = n 187 | return c 188 | } 189 | 190 | m := newNode64(c.key&masks64[bits], bits, false, 0) 191 | m.chld[branch] = n 192 | m.chld[1-branch] = c 193 | 194 | return m 195 | } 196 | 197 | if c.bits == n.bits { 198 | c.chld = n.chld 199 | return c 200 | } 201 | 202 | m := newNode64(n.key, n.bits, n.leaf, n.value) 203 | m.chld = n.chld 204 | 205 | branch := (c.key >> (key64BitSize - 1 - bits)) & 1 206 | m.chld[branch] = m.chld[branch].insert(c) 207 | 208 | return m 209 | } 210 | 211 | func (n *node64) inplaceInsert(key uint64, sbits uint8, value uint32) *node64 { 212 | var ( 213 | p *node64 214 | branch uint64 215 | ) 216 | 217 | r := n 218 | 219 | for n != nil { 220 | cbits := uint8(bits.LeadingZeros64((n.key ^ key) | ^masks64[n.bits] | ^masks64[sbits])) 221 | if cbits < n.bits { 222 | pBranch := branch 223 | branch = (n.key >> (key64BitSize - 1 - cbits)) & 1 224 | 225 | var m *node64 226 | 227 | if cbits == sbits { 228 | m = newNode64(key, sbits, true, value) 229 | m.chld[branch] = n 230 | } else { 231 | m = newNode64(key&masks64[cbits], cbits, false, 0) 232 | m.chld[1-branch] = newNode64(key, sbits, true, value) 233 | } 234 | 235 | m.chld[branch] = n 236 | if p == nil { 237 | r = m 238 | } else { 239 | p.chld[pBranch] = m 240 | } 241 | 242 | return r 243 | } 244 | 245 | if sbits == n.bits { 246 | n.key = key 247 | n.leaf = true 248 | n.value = value 249 | return r 250 | } 251 | 252 | p = n 253 | branch = (key >> (key64BitSize - 1 - cbits)) & 1 254 | n = n.chld[branch] 255 | } 256 | 257 | n = newNode64(key, sbits, true, value) 258 | if p == nil { 259 | return n 260 | } 261 | 262 | p.chld[branch] = n 263 | return r 264 | } 265 | 266 | func (n *node64) enumerate(ch chan *node64) { 267 | if n.leaf { 268 | ch <- n 269 | } 270 | 271 | if n.chld[0] != nil { 272 | n.chld[0].enumerate(ch) 273 | } 274 | 275 | if n.chld[1] != nil { 276 | n.chld[1].enumerate(ch) 277 | } 278 | } 279 | 280 | func (n *node64) match(key uint64, bits uint8) *node64 { 281 | if n.bits > bits { 282 | return nil 283 | } 284 | 285 | if n.bits == bits { 286 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 287 | return n 288 | } 289 | 290 | return nil 291 | } 292 | 293 | if (n.key^key)&masks64[n.bits] != 0 { 294 | return nil 295 | } 296 | 297 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 298 | if c != nil { 299 | r := c.match(key, bits) 300 | if r != nil { 301 | return r 302 | } 303 | } 304 | 305 | if n.leaf { 306 | return n 307 | } 308 | 309 | return nil 310 | } 311 | 312 | func (n *node64) exactMatch(key uint64, bits uint8) *node64 { 313 | if n.bits > bits { 314 | return nil 315 | } 316 | 317 | if n.bits == bits { 318 | if n.leaf && (n.key^key)&masks64[n.bits] == 0 { 319 | return n 320 | } 321 | 322 | return nil 323 | } 324 | 325 | if (n.key^key)&masks64[n.bits] != 0 { 326 | return nil 327 | } 328 | 329 | c := n.chld[(key>>(key64BitSize-1-n.bits))&1] 330 | if c != nil { 331 | r := c.exactMatch(key, bits) 332 | if r != nil { 333 | return r 334 | } 335 | } 336 | 337 | return nil 338 | } 339 | 340 | func (n *node64) del(key uint64, bits uint8) (*node64, bool) { 341 | if bits <= n.bits { 342 | if (n.key^key)&masks64[bits] == 0 { 343 | return nil, true 344 | } 345 | 346 | return n, false 347 | } 348 | 349 | if (n.key^key)&masks64[n.bits] != 0 { 350 | return n, false 351 | } 352 | 353 | branch := (key >> (key64BitSize - 1 - n.bits)) & 1 354 | c := n.chld[branch] 355 | if c == nil { 356 | return n, false 357 | } 358 | 359 | c, ok := c.del(key, bits) 360 | if !ok { 361 | return n, false 362 | } 363 | 364 | if c == nil && !n.leaf { 365 | return n.chld[1-branch], true 366 | } 367 | 368 | m := newNode64(n.key, n.bits, n.leaf, n.value) 369 | m.chld = n.chld 370 | 371 | m.chld[branch] = c 372 | return m, true 373 | } 374 | 375 | func newNode64(key uint64, bits uint8, leaf bool, value uint32) *node64 { 376 | return &node64{ 377 | key: key, 378 | bits: bits, 379 | leaf: leaf, 380 | value: value} 381 | } 382 | --------------------------------------------------------------------------------