htreebucket.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package hash
  11. import (
  12. "bytes"
  13. "fmt"
  14. "devt.de/krotik/common/stringutil"
  15. )
  16. /*
  17. htreeBucket data structure
  18. */
  19. type htreeBucket struct {
  20. *htreeNode
  21. }
  22. /*
  23. htreeBucket creates a new bucket for the HTree.
  24. */
  25. func newHTreeBucket(tree *HTree, depth byte) *htreeBucket {
  26. return &htreeBucket{&htreeNode{tree, 0, nil, depth, nil,
  27. make([][]byte, MaxBucketElements),
  28. make([]interface{}, MaxBucketElements), 0}}
  29. }
  30. /*
  31. Size returns the size of this bucket.
  32. */
  33. func (b *htreeBucket) Size() byte {
  34. return b.BucketSize
  35. }
  36. /*
  37. IsLeaf returns if this bucket is a leaf node.
  38. */
  39. func (b *htreeBucket) IsLeaf() bool {
  40. return b.Depth == MaxTreeDepth+1
  41. }
  42. /*
  43. HasRoom returns if this bucket has room for more data.
  44. */
  45. func (b *htreeBucket) HasRoom() bool {
  46. if b.IsLeaf() {
  47. return true
  48. }
  49. return b.BucketSize < MaxBucketElements
  50. }
  51. /*
  52. Put adds or updates a new key / value pair to the bucket.
  53. */
  54. func (b *htreeBucket) Put(key []byte, value interface{}) interface{} {
  55. if key == nil {
  56. return nil
  57. }
  58. // Check if this is an update
  59. for i, skey := range b.Keys {
  60. if bytes.Compare(key, skey) == 0 {
  61. old := b.Values[i]
  62. b.Values[i] = value
  63. return old
  64. }
  65. }
  66. if !b.HasRoom() {
  67. panic("Bucket has no more room")
  68. }
  69. if b.BucketSize >= MaxBucketElements {
  70. b.Keys = append(b.Keys, key)
  71. b.Values = append(b.Values, value)
  72. b.BucketSize++
  73. return nil
  74. }
  75. b.Keys[b.BucketSize] = key
  76. b.Values[b.BucketSize] = value
  77. b.BucketSize++
  78. return nil
  79. }
  80. /*
  81. Remove removes a key / value pair from the bucket.
  82. */
  83. func (b *htreeBucket) Remove(key []byte) interface{} {
  84. if key == nil || b.BucketSize == 0 {
  85. return nil
  86. }
  87. // Look for the key
  88. for i, skey := range b.Keys {
  89. if bytes.Compare(key, skey) == 0 {
  90. old := b.Values[i]
  91. b.Keys[i] = b.Keys[b.BucketSize-1]
  92. b.Values[i] = b.Values[b.BucketSize-1]
  93. b.Keys[b.BucketSize-1] = nil
  94. b.Values[b.BucketSize-1] = nil
  95. b.BucketSize--
  96. return old
  97. }
  98. }
  99. return nil
  100. }
  101. /*
  102. Get gets the value for a given key.
  103. */
  104. func (b *htreeBucket) Get(key []byte) interface{} {
  105. if key == nil || b.BucketSize == 0 {
  106. return nil
  107. }
  108. // Look for the key
  109. for i, skey := range b.Keys {
  110. if bytes.Compare(key, skey) == 0 {
  111. return b.Values[i]
  112. }
  113. }
  114. return nil
  115. }
  116. /*
  117. Exists checks if an element exists.
  118. */
  119. func (b *htreeBucket) Exists(key []byte) bool {
  120. if key == nil || b.BucketSize == 0 {
  121. return false
  122. }
  123. // Look for the key
  124. for _, skey := range b.Keys {
  125. if bytes.Compare(key, skey) == 0 {
  126. return true
  127. }
  128. }
  129. return false
  130. }
  131. /*
  132. String returns a string representation of this bucket.
  133. */
  134. func (b *htreeBucket) String() string {
  135. var j byte
  136. buf := new(bytes.Buffer)
  137. for j = 0; j < b.Depth; j++ {
  138. buf.WriteString(" ")
  139. }
  140. buf.WriteString(fmt.Sprintf("HashBucket (%v element%s, depth: %v)\n",
  141. b.Size(), stringutil.Plural(int(b.Size())), b.Depth))
  142. for i, key := range b.Keys {
  143. for j = 0; j < b.Depth; j++ {
  144. buf.WriteString(" ")
  145. }
  146. buf.WriteString(fmt.Sprintf("%v - %v\n", key, b.Values[i]))
  147. }
  148. return buf.String()
  149. }