123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package hash
- import (
- "bytes"
- "fmt"
- "devt.de/krotik/common/stringutil"
- )
- /*
- htreeBucket data structure
- */
- type htreeBucket struct {
- *htreeNode
- }
- /*
- htreeBucket creates a new bucket for the HTree.
- */
- func newHTreeBucket(tree *HTree, depth byte) *htreeBucket {
- return &htreeBucket{&htreeNode{tree, 0, nil, depth, nil,
- make([][]byte, MaxBucketElements),
- make([]interface{}, MaxBucketElements), 0}}
- }
- /*
- Size returns the size of this bucket.
- */
- func (b *htreeBucket) Size() byte {
- return b.BucketSize
- }
- /*
- IsLeaf returns if this bucket is a leaf node.
- */
- func (b *htreeBucket) IsLeaf() bool {
- return b.Depth == MaxTreeDepth+1
- }
- /*
- HasRoom returns if this bucket has room for more data.
- */
- func (b *htreeBucket) HasRoom() bool {
- if b.IsLeaf() {
- return true
- }
- return b.BucketSize < MaxBucketElements
- }
- /*
- Put adds or updates a new key / value pair to the bucket.
- */
- func (b *htreeBucket) Put(key []byte, value interface{}) interface{} {
- if key == nil {
- return nil
- }
- // Check if this is an update
- for i, skey := range b.Keys {
- if bytes.Compare(key, skey) == 0 {
- old := b.Values[i]
- b.Values[i] = value
- return old
- }
- }
- if !b.HasRoom() {
- panic("Bucket has no more room")
- }
- if b.BucketSize >= MaxBucketElements {
- b.Keys = append(b.Keys, key)
- b.Values = append(b.Values, value)
- b.BucketSize++
- return nil
- }
- b.Keys[b.BucketSize] = key
- b.Values[b.BucketSize] = value
- b.BucketSize++
- return nil
- }
- /*
- Remove removes a key / value pair from the bucket.
- */
- func (b *htreeBucket) Remove(key []byte) interface{} {
- if key == nil || b.BucketSize == 0 {
- return nil
- }
- // Look for the key
- for i, skey := range b.Keys {
- if bytes.Compare(key, skey) == 0 {
- old := b.Values[i]
- b.Keys[i] = b.Keys[b.BucketSize-1]
- b.Values[i] = b.Values[b.BucketSize-1]
- b.Keys[b.BucketSize-1] = nil
- b.Values[b.BucketSize-1] = nil
- b.BucketSize--
- return old
- }
- }
- return nil
- }
- /*
- Get gets the value for a given key.
- */
- func (b *htreeBucket) Get(key []byte) interface{} {
- if key == nil || b.BucketSize == 0 {
- return nil
- }
- // Look for the key
- for i, skey := range b.Keys {
- if bytes.Compare(key, skey) == 0 {
- return b.Values[i]
- }
- }
- return nil
- }
- /*
- Exists checks if an element exists.
- */
- func (b *htreeBucket) Exists(key []byte) bool {
- if key == nil || b.BucketSize == 0 {
- return false
- }
- // Look for the key
- for _, skey := range b.Keys {
- if bytes.Compare(key, skey) == 0 {
- return true
- }
- }
- return false
- }
- /*
- String returns a string representation of this bucket.
- */
- func (b *htreeBucket) String() string {
- var j byte
- buf := new(bytes.Buffer)
- for j = 0; j < b.Depth; j++ {
- buf.WriteString(" ")
- }
- buf.WriteString(fmt.Sprintf("HashBucket (%v element%s, depth: %v)\n",
- b.Size(), stringutil.Plural(int(b.Size())), b.Depth))
- for i, key := range b.Keys {
- for j = 0; j < b.Depth; j++ {
- buf.WriteString(" ")
- }
- buf.WriteString(fmt.Sprintf("%v - %v\n", key, b.Values[i]))
- }
- return buf.String()
- }
|