Commit d1f6c902 authored by jnml's avatar jnml

Initial commit

parent e21c4f1e
all:
go fmt
go test -i
go test
go build
go vet
go install
make todo
todo:
@grep -n ^[[:space:]]*_[[:space:]]*=[[:space:]][[:alpha:]][[:alnum:]]* *.go || true
@grep -n TODO *.go || true
@grep -n BUG *.go || true
@grep -n println *.go || true
clean:
@go clean
rm -f *~ cov cov.html
gocov:
gocov test $(COV) | gocov-html > cov.html
generic:
@# writes to stdout a version where the type of key is KEY and the type
@# of value is VALUE.
@#
@# Intended use is to replace all textual occurrences of KEY or VALUE in
@# the output with your desired types.
@sed -e 's|interface{}[^{]*/\*K\*/|KEY|g' -e 's|interface{}[^{]*/\*V\*/|VALUE|g' btree.go
......@@ -2,3 +2,9 @@ b
=
Package b implements a B+tree.
Installation:
$ go get github.com/cznic/b
Documentation: [godoc.org/github.com/cznic/b](http://godoc.org/github.com/cznic/b)
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package b
import (
"fmt"
"io"
"math"
"path"
"runtime"
"runtime/debug"
"testing"
"github.com/cznic/mathutil"
)
func use(...interface{}) {}
var dbg = func(s string, va ...interface{}) {
_, fn, fl, _ := runtime.Caller(1)
fmt.Printf("%s:%d: ", path.Base(fn), fl)
fmt.Printf(s, va...)
fmt.Println()
}
var caller = func(s string, va ...interface{}) {
_, fn, fl, _ := runtime.Caller(2)
fmt.Printf("%s:%d: ", path.Base(fn), fl)
fmt.Printf(s, va...)
fmt.Println()
}
func isNil(p interface{}) bool {
switch x := p.(type) {
case *x:
if x == nil {
return true
}
case *d:
if x == nil {
return true
}
}
return false
}
func (t *Tree) dump() string {
num := map[interface{}]int{}
visited := map[interface{}]bool{}
handle := func(p interface{}) int {
if isNil(p) {
return 0
}
if n, ok := num[p]; ok {
return n
}
n := len(num) + 1
num[p] = n
return n
}
var pagedump func(interface{}, string)
pagedump = func(p interface{}, pref string) {
if isNil(p) || visited[p] {
return
}
visited[p] = true
switch x := p.(type) {
case *x:
h := handle(p)
n := 0
for i, v := range x.x {
if v.ch != nil || v.sep != nil {
n = i + 1
}
}
fmt.Printf("%sX#%d n %d:%d {", pref, h, x.c, n)
a := []interface{}{}
for i, v := range x.x[:n] {
a = append(a, v.ch, v.sep)
if i != 0 {
fmt.Printf(" ")
}
fmt.Printf("(C#%d D#%d)", handle(v.ch), handle(v.sep))
}
fmt.Printf("}\n")
for _, p := range a {
pagedump(p, pref+". ")
}
case *d:
h := handle(p)
n := 0
for i, v := range x.d {
if v.k != nil || v.v != nil {
n = i + 1
}
}
fmt.Printf("%sD#%d P#%d N#%d n %d:%d {", pref, h, handle(x.p), handle(x.n), x.c, n)
for i, v := range x.d[:n] {
if i != 0 {
fmt.Printf(" ")
}
fmt.Printf("%v:%v", v.k, v.v)
}
fmt.Printf("}\n")
}
}
pagedump(t.r, "")
return ""
}
func rng() *mathutil.FC32 {
x, err := mathutil.NewFC32(math.MinInt32, math.MaxInt32, false)
if err != nil {
panic(err)
}
return x
}
func cmp(a, b interface{}) int {
return a.(int) - b.(int)
}
func TestGet0(t *testing.T) {
r := TreeNew(cmp)
if g, e := r.Len(), 0; g != e {
t.Fatal(g, e)
}
v, ok := r.Get(42)
if v != nil {
t.Fatal(v)
}
if ok {
t.Fatal(ok)
}
}
func TestSetGet0(t *testing.T) {
r := TreeNew(cmp)
set := r.Set
set(42, 314)
if g, e := r.Len(), 1; g != e {
t.Fatal(g, e)
}
v, ok := r.Get(42)
if !ok {
t.Fatal(ok)
}
if g, e := v.(int), 314; g != e {
t.Fatal(g, e)
}
set(42, 278)
if g, e := r.Len(), 1; g != e {
t.Fatal(g, e)
}
v, ok = r.Get(42)
if !ok {
t.Fatal(ok)
}
if g, e := v.(int), 278; g != e {
t.Fatal(g, e)
}
set(420, 0.5)
if g, e := r.Len(), 2; g != e {
t.Fatal(g, e)
}
v, ok = r.Get(42)
if !ok {
t.Fatal(ok)
}
if g, e := v.(int), 278; g != e {
t.Fatal(g, e)
}
v, ok = r.Get(420)
if !ok {
t.Fatal(ok)
}
if g, e := v.(float64), 0.5; g != e {
t.Fatal(g, e)
}
}
func TestSetGet1(t *testing.T) {
const N = 90000
for _, x := range []int{0, -1, 0x55555555, 0xaaaaaaaa, 314159265} {
r := TreeNew(cmp)
set := r.Set
a := make([]int, N)
for i := range a {
a[i] = (i ^ x) << 1
}
for i, k := range a {
set(k, k^x)
if g, e := r.Len(), i+1; g != e {
t.Fatal(i, g, e)
}
}
for i, k := range a {
v, ok := r.Get(k)
if !ok {
t.Fatal(i, k, v, ok)
}
if v == nil {
t.Fatal(i, k)
}
if g, e := v.(int), k^x; g != e {
t.Fatal(i, g, e)
}
k |= 1
v, ok = r.Get(k)
if ok {
t.Fatal(i, k)
}
if v != nil {
t.Fatal(i, k)
}
}
}
}
func BenchmarkSetSeq(b *testing.B) {
r := TreeNew(cmp)
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.Set(i, i)
}
}
func BenchmarkSetRnd(b *testing.B) {
r := TreeNew(cmp)
rng := rng()
a := make([]int, b.N)
for i := range a {
a[i] = rng.Next()
}
debug.FreeOSMemory()
b.ResetTimer()
for _, v := range a {
r.Set(v, 0)
}
}
func BenchmarkGetSeq(b *testing.B) {
r := TreeNew(cmp)
for i := 0; i < b.N; i++ {
r.Set(i, i)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.Get(i)
}
}
func BenchmarkGetRnd(b *testing.B) {
r := TreeNew(cmp)
rng := rng()
a := make([]int, b.N)
for i := range a {
a[i] = rng.Next()
}
for _, v := range a {
r.Set(v, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for _, v := range a {
r.Get(v)
}
}
func TestSetGet2(t *testing.T) {
const N = 70000
for _, x := range []int{0, -1, 0x55555555, 0xaaaaaaaa, 314159265} {
r := TreeNew(cmp)
set := r.Set
a := make([]int, N)
rng := rng()
for i := range a {
a[i] = (rng.Next() ^ x) << 1
}
for i, k := range a {
set(k, k^x)
if g, e := r.Len(), i+1; g != e {
t.Fatal(i, x, g, e)
}
}
for i, k := range a {
v, ok := r.Get(k)
if !ok {
t.Fatal(i, k, v, ok)
}
if v == nil {
t.Fatal(i, k)
}
if g, e := v.(int), k^x; g != e {
t.Fatal(i, g, e)
}
k |= 1
v, ok = r.Get(k)
if ok {
t.Fatal(i, k)
}
if v != nil {
t.Fatal(i, k)
}
}
}
}
func TestSetGet3(t *testing.T) {
r := TreeNew(cmp)
set := r.Set
var i int
for i = 0; ; i++ {
set(i, -i)
if _, ok := r.r.(*x); ok {
break
}
}
for j := 0; j <= i; j++ {
set(j, j)
}
for j := 0; j <= i; j++ {
v, ok := r.Get(j)
if !ok {
t.Fatal(j)
}
if v == nil {
t.Fatal(j)
}
if g, e := v.(int), j; g != e {
t.Fatal(g, e)
}
}
}
func TestDelete0(t *testing.T) {
r := TreeNew(cmp)
if ok := r.Delete(0); ok {
t.Fatal(ok)
}
if g, e := r.Len(), 0; g != e {
t.Fatal(g, e)
}
r.Set(0, 0)
if ok := r.Delete(1); ok {
t.Fatal(ok)
}
if g, e := r.Len(), 1; g != e {
t.Fatal(g, e)
}
if ok := r.Delete(0); !ok {
t.Fatal(ok)
}
if g, e := r.Len(), 0; g != e {
t.Fatal(g, e)
}
if ok := r.Delete(0); ok {
t.Fatal(ok)
}
r.Set(0, 0)
r.Set(1, 1)
if ok := r.Delete(1); !ok {
t.Fatal(ok)
}
if g, e := r.Len(), 1; g != e {
t.Fatal(g, e)
}
if ok := r.Delete(1); ok {
t.Fatal(ok)
}
if ok := r.Delete(0); !ok {
t.Fatal(ok)
}
if g, e := r.Len(), 0; g != e {
t.Fatal(g, e)
}
if ok := r.Delete(0); ok {
t.Fatal(ok)
}
r.Set(0, 0)
r.Set(1, 1)
if ok := r.Delete(0); !ok {
t.Fatal(ok)
}
if g, e := r.Len(), 1; g != e {
t.Fatal(g, e)
}
if ok := r.Delete(0); ok {
t.Fatal(ok)
}
if ok := r.Delete(1); !ok {
t.Fatal(ok)
}
if g, e := r.Len(), 0; g != e {
t.Fatal(g, e)
}
if ok := r.Delete(1); ok {
t.Fatal(ok)
}
}
func TestDelete1(t *testing.T) {
const N = 100000
for _, x := range []int{0, -1, 0x55555555, 0xaaaaaaaa, 314159265} {
r := TreeNew(cmp)
set := r.Set
a := make([]int, N)
for i := range a {
a[i] = (i ^ x) << 1
}
for _, k := range a {
set(k, 0)
}
for i, k := range a {
ok := r.Delete(k)
if !ok {
t.Fatal(i, x, k)
}
if g, e := r.Len(), N-i-1; g != e {
t.Fatal(i, g, e)
}
}
}
}
func BenchmarkDelSeq(b *testing.B) {
r := TreeNew(cmp)
for i := 0; i < b.N; i++ {
r.Set(i, i)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.Delete(i)
}
}
func BenchmarkDelRnd(b *testing.B) {
r := TreeNew(cmp)
rng := rng()
a := make([]int, b.N)
for i := range a {
a[i] = rng.Next()
}
for _, v := range a {
r.Set(v, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for _, v := range a {
r.Delete(v)
}
}
func TestDelete2(t *testing.T) {
const N = 100000
for _, x := range []int{0, -1, 0x55555555, 0xaaaaaaaa, 314159265} {
r := TreeNew(cmp)
set := r.Set
a := make([]int, N)
rng := rng()
for i := range a {
a[i] = (rng.Next() ^ x) << 1
}
for _, k := range a {
set(k, 0)
}
for i, k := range a {
ok := r.Delete(k)
if !ok {
t.Fatal(i, x, k)
}
if g, e := r.Len(), N-i-1; g != e {
t.Fatal(i, g, e)
}
}
}
}
func TestEnumeratorNext(t *testing.T) {
// seeking within 3 keys: 10, 20, 30
table := []struct {
k int
hit bool
keys []int
}{
{5, false, []int{10, 20, 30}},
{10, true, []int{10, 20, 30}},
{15, false, []int{20, 30}},
{20, true, []int{20, 30}},
{25, false, []int{30}},
{30, true, []int{30}},
{35, false, []int{}},
}
for i, test := range table {
up := test.keys
r := TreeNew(cmp)
r.Set(10, 100)
r.Set(20, 200)
r.Set(30, 300)
for verChange := 0; verChange < 16; verChange++ {
t.Logf("Seek %d", test.k)
en, hit := r.Seek(test.k)
if g, e := hit, test.hit; g != e {
t.Fatal(i, g, e)
}
j := 0
for {
if verChange&(1<<uint(j)) != 0 {
t.Log("version change")
r.Set(20, 200)
}
k, v, err := en.Next()
if err != nil {
if err != io.EOF {
t.Fatal(i, err)
}
break
}
t.Logf("Next -> %v: %v", k, v)
if j >= len(up) {
t.Fatal(i, j, verChange)
}
if g, e := k.(int), up[j]; g != e {
t.Fatal(i, j, verChange, g, e)
}
if g, e := v.(int), 10*up[j]; g != e {
t.Fatal(i, g, e)
}
j++
}
if g, e := j, len(up); g != e {
t.Fatal(i, j, g, e)
}
}
}
}
func TestEnumeratorPrev(t *testing.T) {
// seeking within 3 keys: 10, 20, 30
table := []struct {
k int
hit bool
keys []int
}{
{5, false, []int{10}},
{10, true, []int{10}},
{15, false, []int{20, 10}},
{20, true, []int{20, 10}},
{25, false, []int{30, 20, 10}},
{30, true, []int{30, 20, 10}},
{35, false, []int{}},
}
for i, test := range table {
dn := test.keys
r := TreeNew(cmp)
r.Set(10, 100)
r.Set(20, 200)
r.Set(30, 300)
for verChange := 0; verChange < 16; verChange++ {
t.Logf("Seek %d", test.k)
en, hit := r.Seek(test.k)
if g, e := hit, test.hit; g != e {
t.Fatal(i, g, e)
}
j := 0
for {
if verChange&(1<<uint(j)) != 0 {
t.Log("version change")
r.Set(20, 200)
}
k, v, err := en.Prev()
if err != nil {
if err != io.EOF {
t.Fatal(i, err)
}
break
}
t.Logf("Prev -> %v: %v", k, v)
if j >= len(dn) {
t.Fatal(i, j, verChange)
}
if g, e := k.(int), dn[j]; g != e {
t.Fatal(i, j, verChange, g, e)
}
if g, e := v.(int), 10*dn[j]; g != e {
t.Fatal(i, g, e)
}
j++
}
if g, e := j, len(dn); g != e {
t.Fatal(i, j, g, e)
}
}
}
}
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package b implements a B+tree.
//
// Keys and their associated values are interface{} typed, similarly to all of
// the containers in the standard library.
//
// Semiautomatic production of a type specific variant of this package is
// supported via
//
// $ make generic
//
// Performing it will write to stdout a version of the btree.go file where
// every key type occurrence is replaced by the word KEY and every value type
// occurrence is replaced by the word VALUE. In both cases as seen here, ie.
// all upper case letters. Then you have to replace the strings {KEY,VALUE}
// with your desired type(s), using any technique you're comfortable with.
package b
import (
"io"
)
//TODO check vs orig initialize/finalize
const (
kx = 128 //TODO benchmark tune this number if key type is not interface{}
kd = 64 //TODO benchmark tune this number if value type is not interface{}
)
type (
// Cmp compares a and b. Return value is:
//
// -1 if a < b
// 0 if a == b
// +1 if a > b
Cmp func(a, b interface{} /*K*/) int
d struct { // data page
c int
d [2*kd + 1]de
n *d
p *d
}
de struct { // d element
k interface{} /*K*/
v interface{} /*V*/
}
// Enumerator captures the state of enumerating a tree. It is returned
// from the Seek* methods. The enumerator is aware of any mutations
// made to the tree in the process of enumerating it and automatically
// resumes the enumeration at the proper key, if possible.
//
// However, once an Enumerator returns io.EOF to signal "no more
// items", it does no more attempt to "resync" on tree mutation(s). In
// other words, io.EOF from an Enumaretor is "sticky" (idempotent).
Enumerator struct {
err error
hit bool
i int
k interface{} /*K*/
q *d
t *Tree
ver int64
}
// Tree is a B+tree.
Tree struct {
c int
cmp Cmp
first *d
last *d
r interface{}
ver int64
}
xe struct { // x element
ch interface{}
sep *d
}
x struct { // index page
c int
x [2*kx + 2]xe
}
)
var ( // R/O zero values
zd d
zde de
zx x
zxe xe
)
func clr(q interface{}) {
switch x := q.(type) {
case *x:
for i := 0; i <= x.c; i++ { // Ch0 Sep0 ... Chn-1 Sepn-1 Chn
clr(x.x[i].ch)
}
*x = zx // GC
case *d:
*x = zd // GC
}
}
// -------------------------------------------------------------------------- x
func newX(ch0 interface{}) *x {
r := &x{}
r.x[0].ch = ch0
return r
}
func (q *x) extract(i int) {
q.c--
if i < q.c {
copy(q.x[i:], q.x[i+1:q.c+1])
q.x[q.c].ch = q.x[q.c+1].ch
q.x[q.c].sep = nil // GC
q.x[q.c+1] = zxe // GC
}
}
func (q *x) insert(i int, d *d, ch interface{}) *x {
c := q.c
if i < c {
q.x[c+1].ch = q.x[c].ch
copy(q.x[i+2:], q.x[i+1:c])
q.x[i+1].sep = q.x[i].sep
}
c++
q.c = c
q.x[i].sep = d
q.x[i+1].ch = ch
return q
}
func (q *x) siblings(i int) (l, r *d) {
if i >= 0 {
if i > 0 {
l = q.x[i-1].ch.(*d)
}
if i < q.c {
r = q.x[i+1].ch.(*d)
}
}
return
}
// -------------------------------------------------------------------------- d
func (l *d) mvL(r *d, c int) {
copy(l.d[l.c:], r.d[:c])
copy(r.d[:], r.d[c:r.c])
l.c += c
r.c -= c
}
func (l *d) mvR(r *d, c int) {
copy(r.d[c:], r.d[:r.c])
copy(r.d[:c], l.d[l.c-c:])
r.c += c
l.c -= c
}
// ----------------------------------------------------------------------- Tree
// TreeNew returns a newly created, empty Tree. The compare function is used
// for key collation.
func TreeNew(cmp Cmp) *Tree {
return &Tree{cmp: cmp}
}
// Clear removes all K/V pairs from the tree.
func (t *Tree) Clear() {
if t.r == nil {
return
}
clr(t.r)
t.c, t.first, t.last, t.r = 0, nil, nil, nil
t.ver++
}
func (t *Tree) cat(p *x, q, r *d, pi int) {
q.mvL(r, r.c)
if r.n != nil {
r.n.p = q
} else {
t.last = q
}
q.n = r.n //TODO recycle r
if p.c > 1 {
p.extract(pi)
p.x[pi].ch = q
} else { //TODO recycle r
t.r = q
}
}
func (t *Tree) catX(p, q, r *x, pi int) {
q.x[q.c].sep = p.x[pi].sep
copy(q.x[q.c+1:], r.x[:r.c])
q.c += r.c + 1
q.x[q.c].ch = r.x[r.c].ch //TODO recycle r
if p.c > 1 {
p.c--
pc := p.c
if pi < pc {
p.x[pi].sep = p.x[pi+1].sep
copy(p.x[pi+1:], p.x[pi+2:pc+1])
p.x[pc].ch = p.x[pc+1].ch
p.x[pc].sep = nil // GC
p.x[pc+1].ch = nil // GC
}
return
}
t.r = q //TODO recycle r
}
//Delete removes the k's KV pair, if it exists, in which case Delete returns
//true.
func (t *Tree) Delete(k interface{} /*K*/) (ok bool) {
pi := -1
var p *x
q := t.r
if q == nil {
return
}
for {
var i int
i, ok = t.find(q, k)
if ok {
switch x := q.(type) {
case *x:
dp := x.x[i].sep
switch {
case dp.c > kd:
t.extract(dp, 0)
default:
if x.c < kx && q != t.r {
t.underflowX(p, &x, pi, &i)
}
pi = i + 1
p = x
q = x.x[pi].ch
ok = false
continue
}
case *d:
t.extract(x, i)
t.ver++
if x.c >= kd {
return
}
if q != t.r {
t.underflow(p, x, pi)
} else if t.c == 0 {
t.Clear()
}
}
return
}
switch x := q.(type) {
case *x:
if x.c < kx && q != t.r {
t.underflowX(p, &x, pi, &i)
}
pi = i
p = x
q = x.x[i].ch
case *d:
return
}
}
}
func (t *Tree) extract(q *d, i int) { // (r interface{} /*V*/) {
//r = q.d[i].v // prepared for Extract
q.c--
if i < q.c {
copy(q.d[i:], q.d[i+1:q.c+1])
}
q.d[q.c] = zde // GC
t.c--
return
}
func (t *Tree) find(q interface{}, k interface{} /*K*/) (i int, ok bool) {
var mk interface{} /*K*/
l := 0
switch x := q.(type) {
case *x:
h := x.c - 1
for l <= h {
m := (l + h) >> 1
mk = x.x[m].sep.d[0].k
switch cmp := t.cmp(k, mk); {
case cmp > 0:
l = m + 1
case cmp == 0:
return m, true
default:
h = m - 1
}
}
case *d:
h := x.c - 1
for l <= h {
m := (l + h) >> 1
mk = x.d[m].k
switch cmp := t.cmp(k, mk); {
case cmp > 0:
l = m + 1
case cmp == 0:
return m, true
default:
h = m - 1
}
}
}
return l, false
}
// First returns the first item of the tree in the key collating order, or
// (nil, nil) if the tree is empty.
func (t *Tree) First() (k interface{} /*K*/, v interface{} /*V*/) {
if q := t.first; q != nil {
q := &q.d[0]
k, v = q.k, q.v
}
return
}
// Get returns the value associated with k and true if it exists. Otherwise Get
// returns (nil, false).
func (t *Tree) Get(k interface{} /*K*/) (v interface{} /*V*/, ok bool) {
q := t.r
if q == nil {
return
}
for {
var i int
if i, ok = t.find(q, k); ok {
switch x := q.(type) {
case *x:
return x.x[i].sep.d[0].v, true
case *d:
return x.d[i].v, true
}
}
switch x := q.(type) {
case *x:
q = x.x[i].ch
default:
return
}
}
}
func (t *Tree) insert(q *d, i int, k interface{} /*K*/, v interface{} /*V*/) *d {
c := q.c
if i < c {
copy(q.d[i+1:], q.d[i:c])
}
c++
q.c = c
q.d[i].k, q.d[i].v = k, v
t.c++
return q
}
// Last returns the last item of the tree in the key collating order, or (nil,
// nil) if the tree is empty.
func (t *Tree) Last() (k interface{} /*K*/, v interface{} /*V*/) {
if q := t.last; q != nil {
q := &q.d[q.c-1]
k, v = q.k, q.v
}
return
}
// Len returns the number of items in the tree.
func (t *Tree) Len() int {
return t.c
}
func (t *Tree) overflow(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{} /*V*/) {
l, r := p.siblings(pi)
if l != nil && l.c < 2*kd {
l.mvL(q, 1)
t.insert(q, i-1, k, v)
return
}
if r != nil && r.c < 2*kd {
if i < 2*kd {
q.mvR(r, 1)
t.insert(q, i, k, v)
} else {
t.insert(r, 0, k, v)
}
return
}
t.split(p, q, pi, i, k, v)
}
// Seek returns an Enumerator positioned on a an item such that k >= item's
// key. ok reports if k == item.key The Enumerator's position is possibly
// after the last item in the tree.
func (t *Tree) Seek(k interface{} /*K*/) (e *Enumerator, ok bool) {
q := t.r
if q == nil {
e = &Enumerator{nil, false, 0, k, nil, t, t.ver}
return
}
for {
var i int
if i, ok = t.find(q, k); ok {
switch x := q.(type) {
case *x:
e = &Enumerator{nil, ok, 0, k, x.x[i].sep, t, t.ver}
return
case *d:
e = &Enumerator{nil, ok, i, k, x, t, t.ver}
return
}
}
switch x := q.(type) {
case *x:
q = x.x[i].ch
case *d:
e = &Enumerator{nil, ok, i, k, x, t, t.ver}
return
}
}
}
// Set sets the value associated with k.
func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
t.ver++
pi := -1
var p *x
q := t.r
if q != nil {
for {
i, ok := t.find(q, k)
if ok {
switch x := q.(type) {
case *x:
x.x[i].sep.d[0].v = v
case *d:
x.d[i].v = v
}
return
}
switch x := q.(type) {
case *x:
if x.c > 2*kx {
t.splitX(p, &x, pi, &i)
}
pi = i
p = x
q = x.x[i].ch
case *d:
switch {
case x.c < 2*kd:
t.insert(x, i, k, v)
default:
t.overflow(p, x, pi, i, k, v)
}
return
}
}
}
z := t.insert(&d{}, 0, k, v)
t.r, t.first, t.last = z, z, z
return
}
func (t *Tree) split(p *x, q *d, pi, i int, k interface{} /*K*/, v interface{} /*V*/) {
r := &d{}
if q.n != nil {
r.n = q.n
r.n.p = r
} else {
t.last = r
}
q.n = r
r.p = q
copy(r.d[:], q.d[kd:2*kd])
for i := range q.d[kd:] {
q.d[kd+i] = zde
}
q.c = kd
r.c = kd
if pi >= 0 {
p.insert(pi, r, r)
} else {
t.r = newX(q).insert(0, r, r)
}
if i > kd {
t.insert(r, i-kd, k, v)
return
}
t.insert(q, i, k, v)
}
func (t *Tree) splitX(p *x, pp **x, pi int, i *int) {
q := *pp
r := &x{}
copy(r.x[:], q.x[kx+1:])
q.c = kx
r.c = kx
if pi >= 0 {
p.insert(pi, q.x[kx].sep, r)
} else {
t.r = newX(q).insert(0, q.x[kx].sep, r)
}
q.x[kx].sep = nil
for i := range q.x[kx+1:] {
q.x[kx+i+1] = zxe
}
if *i > kx {
*pp = r
*i -= kx + 1
}
}
func (t *Tree) underflow(p *x, q *d, pi int) {
l, r := p.siblings(pi)
if l != nil && l.c+q.c >= 2*kd {
l.mvR(q, 1)
} else if r != nil && q.c+r.c >= 2*kd {
q.mvL(r, 1)
r.d[r.c] = zde // GC
} else if l != nil {
t.cat(p, l, q, pi-1)
} else {
t.cat(p, q, r, pi)
}
}
func (t *Tree) underflowX(p *x, pp **x, pi int, i *int) {
var l, r *x
q := *pp
if pi >= 0 {
if pi > 0 {
l = p.x[pi-1].ch.(*x)
}
if pi < p.c {
r = p.x[pi+1].ch.(*x)
}
}
if l != nil && l.c > kx {
q.x[q.c+1].ch = q.x[q.c].ch
copy(q.x[1:], q.x[:q.c])
q.x[0].ch = l.x[l.c].ch
q.x[0].sep = p.x[pi-1].sep
q.c++
*i++
l.c--
p.x[pi-1].sep = l.x[l.c].sep
return
}
if r != nil && r.c > kx {
q.x[q.c].sep = p.x[pi].sep
q.c++
q.x[q.c].ch = r.x[0].ch
p.x[pi].sep = r.x[0].sep
copy(r.x[:], r.x[1:r.c])
r.c--
rc := r.c
r.x[rc].ch = r.x[rc+1].ch
r.x[rc].sep = nil
r.x[rc+1].ch = nil
return
}
if l != nil {
*i += l.c + 1
t.catX(p, l, q, pi-1)
*pp = l
return
}
t.catX(p, q, r, pi)
}
// ----------------------------------------------------------------- Enumerator
// Next returns the currently enumerated item, if it exists and moves to the
// next item in the key collation order. If there is no item to return, err ==
// io.EOF is returned.
func (e *Enumerator) Next() (k interface{} /*K*/, v interface{} /*V*/, err error) {
if err = e.err; err != nil {
return
}
if e.ver != e.t.ver {
f, hit := e.t.Seek(e.k)
if !e.hit && hit {
if err = f.next(); err != nil {
return
}
}
*e = *f
}
if e.q == nil {
e.err, err = io.EOF, io.EOF
return
}
if e.i >= e.q.c {
if err = e.next(); err != nil {
return
}
}
i := e.q.d[e.i]
k, v = i.k, i.v
e.k, e.hit = k, false
e.next()
return
}
func (e *Enumerator) next() error {
if e.q == nil {
e.err = io.EOF
return io.EOF
}
switch {
case e.i < e.q.c-1:
e.i++
default:
if e.q, e.i = e.q.n, 0; e.q == nil {
e.err = io.EOF
}
}
return e.err
}
// Prev returns the currently enumerated item, if it exists and moves to the
// previous item in the key collation order. If there is no item to return, err
// == io.EOF is returned.
func (e *Enumerator) Prev() (k interface{} /*K*/, v interface{} /*V*/, err error) {
if err = e.err; err != nil {
return
}
if e.ver != e.t.ver {
f, hit := e.t.Seek(e.k)
if !e.hit && hit {
if err = f.prev(); err != nil {
return
}
}
*e = *f
}
if e.q == nil {
e.err, err = io.EOF, io.EOF
return
}
if e.i >= e.q.c {
if err = e.next(); err != nil {
return
}
}
i := e.q.d[e.i]
k, v = i.k, i.v
e.k, e.hit = k, false
e.prev()
return
}
func (e *Enumerator) prev() error {
if e.q == nil {
e.err = io.EOF
return io.EOF
}
switch {
case e.i > 0:
e.i--
default:
if e.q = e.q.p; e.q == nil {
e.err = io.EOF
break
}
e.i = e.q.c - 1
}
return e.err
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment