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