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  }