github.com/alexandrestein/gods@v1.0.1/trees/btree/iterator.go (about) 1 // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package btree 6 7 import "github.com/alexandrestein/gods/containers" 8 9 func assertIteratorImplementation() { 10 var _ containers.ReverseIteratorWithKey = (*Iterator)(nil) 11 } 12 13 // Iterator holding the iterator's state 14 type Iterator struct { 15 tree *Tree 16 node *Node 17 entry *Entry 18 position position 19 } 20 21 type position byte 22 23 const ( 24 begin, between, end position = 0, 1, 2 25 ) 26 27 // Iterator returns a stateful iterator whose elements are key/value pairs. 28 func (tree *Tree) Iterator() Iterator { 29 return Iterator{tree: tree, node: nil, position: begin} 30 } 31 32 // Next moves the iterator to the next element and returns true if there was a next element in the container. 33 // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). 34 // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 35 // Modifies the state of the iterator. 36 func (iterator *Iterator) Next() bool { 37 // If already at end, go to end 38 if iterator.position == end { 39 goto end 40 } 41 // If at beginning, get the left-most entry in the tree 42 if iterator.position == begin { 43 left := iterator.tree.Left() 44 if left == nil { 45 goto end 46 } 47 iterator.node = left 48 iterator.entry = left.Entries[0] 49 goto between 50 } 51 { 52 // Find current entry position in current node 53 e, _ := iterator.tree.search(iterator.node, iterator.entry.Key) 54 // Try to go down to the child right of the current entry 55 if e+1 < len(iterator.node.Children) { 56 iterator.node = iterator.node.Children[e+1] 57 // Try to go down to the child left of the current node 58 for len(iterator.node.Children) > 0 { 59 iterator.node = iterator.node.Children[0] 60 } 61 // Return the left-most entry 62 iterator.entry = iterator.node.Entries[0] 63 goto between 64 } 65 // Above assures that we have reached a leaf node, so return the next entry in current node (if any) 66 if e+1 < len(iterator.node.Entries) { 67 iterator.entry = iterator.node.Entries[e+1] 68 goto between 69 } 70 } 71 // Reached leaf node and there are no entries to the right of the current entry, so go up to the parent 72 for iterator.node.Parent != nil { 73 iterator.node = iterator.node.Parent 74 // Find next entry position in current node (note: search returns the first equal or bigger than entry) 75 e, _ := iterator.tree.search(iterator.node, iterator.entry.Key) 76 // Check that there is a next entry position in current node 77 if e < len(iterator.node.Entries) { 78 iterator.entry = iterator.node.Entries[e] 79 goto between 80 } 81 } 82 83 end: 84 iterator.End() 85 return false 86 87 between: 88 iterator.position = between 89 return true 90 } 91 92 // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 93 // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). 94 // Modifies the state of the iterator. 95 func (iterator *Iterator) Prev() bool { 96 // If already at beginning, go to begin 97 if iterator.position == begin { 98 goto begin 99 } 100 // If at end, get the right-most entry in the tree 101 if iterator.position == end { 102 right := iterator.tree.Right() 103 if right == nil { 104 goto begin 105 } 106 iterator.node = right 107 iterator.entry = right.Entries[len(right.Entries)-1] 108 goto between 109 } 110 { 111 // Find current entry position in current node 112 e, _ := iterator.tree.search(iterator.node, iterator.entry.Key) 113 // Try to go down to the child left of the current entry 114 if e < len(iterator.node.Children) { 115 iterator.node = iterator.node.Children[e] 116 // Try to go down to the child right of the current node 117 for len(iterator.node.Children) > 0 { 118 iterator.node = iterator.node.Children[len(iterator.node.Children)-1] 119 } 120 // Return the right-most entry 121 iterator.entry = iterator.node.Entries[len(iterator.node.Entries)-1] 122 goto between 123 } 124 // Above assures that we have reached a leaf node, so return the previous entry in current node (if any) 125 if e-1 >= 0 { 126 iterator.entry = iterator.node.Entries[e-1] 127 goto between 128 } 129 } 130 // Reached leaf node and there are no entries to the left of the current entry, so go up to the parent 131 for iterator.node.Parent != nil { 132 iterator.node = iterator.node.Parent 133 // Find previous entry position in current node (note: search returns the first equal or bigger than entry) 134 e, _ := iterator.tree.search(iterator.node, iterator.entry.Key) 135 // Check that there is a previous entry position in current node 136 if e-1 >= 0 { 137 iterator.entry = iterator.node.Entries[e-1] 138 goto between 139 } 140 } 141 142 begin: 143 iterator.Begin() 144 return false 145 146 between: 147 iterator.position = between 148 return true 149 } 150 151 // Value returns the current element's value. 152 // Does not modify the state of the iterator. 153 func (iterator *Iterator) Value() interface{} { 154 return iterator.entry.Value 155 } 156 157 // Key returns the current element's key. 158 // Does not modify the state of the iterator. 159 func (iterator *Iterator) Key() interface{} { 160 return iterator.entry.Key 161 } 162 163 // Begin resets the iterator to its initial state (one-before-first) 164 // Call Next() to fetch the first element if any. 165 func (iterator *Iterator) Begin() { 166 iterator.node = nil 167 iterator.position = begin 168 iterator.entry = nil 169 } 170 171 // End moves the iterator past the last element (one-past-the-end). 172 // Call Prev() to fetch the last element if any. 173 func (iterator *Iterator) End() { 174 iterator.node = nil 175 iterator.position = end 176 iterator.entry = nil 177 } 178 179 // First moves the iterator to the first element and returns true if there was a first element in the container. 180 // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). 181 // Modifies the state of the iterator 182 func (iterator *Iterator) First() bool { 183 iterator.Begin() 184 return iterator.Next() 185 } 186 187 // Last moves the iterator to the last element and returns true if there was a last element in the container. 188 // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). 189 // Modifies the state of the iterator. 190 func (iterator *Iterator) Last() bool { 191 iterator.End() 192 return iterator.Prev() 193 }