本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
6.1KB

  1. package merkletrie
  2. import (
  3. "fmt"
  4. "io"
  5. "gopkg.in/src-d/go-git.v4/utils/merkletrie/internal/frame"
  6. "gopkg.in/src-d/go-git.v4/utils/merkletrie/noder"
  7. )
  8. // Iter is an iterator for merkletries (only the trie part of the
  9. // merkletrie is relevant here, it does not use the Hasher interface).
  10. //
  11. // The iteration is performed in depth-first pre-order. Entries at each
  12. // depth are traversed in (case-sensitive) alphabetical order.
  13. //
  14. // This is the kind of traversal you will expect when listing ordinary
  15. // files and directories recursively, for example:
  16. //
  17. // Trie Traversal order
  18. // ---- ---------------
  19. // .
  20. // / | \ c
  21. // / | \ d/
  22. // d c z ===> d/a
  23. // / \ d/b
  24. // b a z
  25. //
  26. //
  27. // This iterator is somewhat especial as you can chose to skip whole
  28. // "directories" when iterating:
  29. //
  30. // - The Step method will iterate normally.
  31. //
  32. // - the Next method will not descend deeper into the tree.
  33. //
  34. // For example, if the iterator is at `d/`, the Step method will return
  35. // `d/a` while the Next would have returned `z` instead (skipping `d/`
  36. // and its descendants). The name of the these two methods are based on
  37. // the well known "next" and "step" operations, quite common in
  38. // debuggers, like gdb.
  39. //
  40. // The paths returned by the iterator will be relative, if the iterator
  41. // was created from a single node, or absolute, if the iterator was
  42. // created from the path to the node (the path will be prefixed to all
  43. // returned paths).
  44. type Iter struct {
  45. // Tells if the iteration has started.
  46. hasStarted bool
  47. // The top of this stack has the current node and its siblings. The
  48. // rest of the stack keeps the ancestors of the current node and
  49. // their corresponding siblings. The current element is always the
  50. // top element of the top frame.
  51. //
  52. // When "step"ping into a node, its children are pushed as a new
  53. // frame.
  54. //
  55. // When "next"ing pass a node, the current element is dropped by
  56. // popping the top frame.
  57. frameStack []*frame.Frame
  58. // The base path used to turn the relative paths used internally by
  59. // the iterator into absolute paths used by external applications.
  60. // For relative iterator this will be nil.
  61. base noder.Path
  62. }
  63. // NewIter returns a new relative iterator using the provider noder as
  64. // its unnamed root. When iterating, all returned paths will be
  65. // relative to node.
  66. func NewIter(n noder.Noder) (*Iter, error) {
  67. return newIter(n, nil)
  68. }
  69. // NewIterFromPath returns a new absolute iterator from the noder at the
  70. // end of the path p. When iterating, all returned paths will be
  71. // absolute, using the root of the path p as their root.
  72. func NewIterFromPath(p noder.Path) (*Iter, error) {
  73. return newIter(p, p) // Path implements Noder
  74. }
  75. func newIter(root noder.Noder, base noder.Path) (*Iter, error) {
  76. ret := &Iter{
  77. base: base,
  78. }
  79. if root == nil {
  80. return ret, nil
  81. }
  82. frame, err := frame.New(root)
  83. if err != nil {
  84. return nil, err
  85. }
  86. ret.push(frame)
  87. return ret, nil
  88. }
  89. func (iter *Iter) top() (*frame.Frame, bool) {
  90. if len(iter.frameStack) == 0 {
  91. return nil, false
  92. }
  93. top := len(iter.frameStack) - 1
  94. return iter.frameStack[top], true
  95. }
  96. func (iter *Iter) push(f *frame.Frame) {
  97. iter.frameStack = append(iter.frameStack, f)
  98. }
  99. const (
  100. doDescend = true
  101. dontDescend = false
  102. )
  103. // Next returns the path of the next node without descending deeper into
  104. // the trie and nil. If there are no more entries in the trie it
  105. // returns nil and io.EOF. In case of error, it will return nil and the
  106. // error.
  107. func (iter *Iter) Next() (noder.Path, error) {
  108. return iter.advance(dontDescend)
  109. }
  110. // Step returns the path to the next node in the trie, descending deeper
  111. // into it if needed, and nil. If there are no more nodes in the trie,
  112. // it returns nil and io.EOF. In case of error, it will return nil and
  113. // the error.
  114. func (iter *Iter) Step() (noder.Path, error) {
  115. return iter.advance(doDescend)
  116. }
  117. // Advances the iterator in the desired direction: descend or
  118. // dontDescend.
  119. //
  120. // Returns the new current element and a nil error on success. If there
  121. // are no more elements in the trie below the base, it returns nil, and
  122. // io.EOF. Returns nil and an error in case of errors.
  123. func (iter *Iter) advance(wantDescend bool) (noder.Path, error) {
  124. current, err := iter.current()
  125. if err != nil {
  126. return nil, err
  127. }
  128. // The first time we just return the current node.
  129. if !iter.hasStarted {
  130. iter.hasStarted = true
  131. return current, nil
  132. }
  133. // Advances means getting a next current node, either its first child or
  134. // its next sibling, depending if we must descend or not.
  135. numChildren, err := current.NumChildren()
  136. if err != nil {
  137. return nil, err
  138. }
  139. mustDescend := numChildren != 0 && wantDescend
  140. if mustDescend {
  141. // descend: add a new frame with the current's children.
  142. frame, err := frame.New(current)
  143. if err != nil {
  144. return nil, err
  145. }
  146. iter.push(frame)
  147. } else {
  148. // don't descend: just drop the current node
  149. iter.drop()
  150. }
  151. return iter.current()
  152. }
  153. // Returns the path to the current node, adding the base if there was
  154. // one, and a nil error. If there were no noders left, it returns nil
  155. // and io.EOF. If an error occurred, it returns nil and the error.
  156. func (iter *Iter) current() (noder.Path, error) {
  157. if topFrame, ok := iter.top(); !ok {
  158. return nil, io.EOF
  159. } else if _, ok := topFrame.First(); !ok {
  160. return nil, io.EOF
  161. }
  162. ret := make(noder.Path, 0, len(iter.base)+len(iter.frameStack))
  163. // concat the base...
  164. ret = append(ret, iter.base...)
  165. // ... and the current node and all its ancestors
  166. for i, f := range iter.frameStack {
  167. t, ok := f.First()
  168. if !ok {
  169. panic(fmt.Sprintf("frame %d is empty", i))
  170. }
  171. ret = append(ret, t)
  172. }
  173. return ret, nil
  174. }
  175. // removes the current node if any, and all the frames that become empty as a
  176. // consequence of this action.
  177. func (iter *Iter) drop() {
  178. frame, ok := iter.top()
  179. if !ok {
  180. return
  181. }
  182. frame.Drop()
  183. // if the frame is empty, remove it and its parent, recursively
  184. if frame.Len() == 0 {
  185. top := len(iter.frameStack) - 1
  186. iter.frameStack[top] = nil
  187. iter.frameStack = iter.frameStack[:top]
  188. iter.drop()
  189. }
  190. }
上海开阖软件有限公司 沪ICP备12045867号-1