github.com/mymmsc/gox@v1.3.33/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  	"github.com/mymmsc/gox/util"
     9  )
    10  
    11  func assertIteratorImplementation() {
    12  	var _ util.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  }