diff options
author | Alberto Cortés <alcortesm@gmail.com> | 2017-02-06 17:40:38 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-06 17:40:38 +0100 |
commit | 41e5a1ff6f16ec13fa1cebe6e1d872bfe0951cee (patch) | |
tree | 6952a48ac8a6bb23c86f1568faca70614badfeaa /utils/merkletrie/internal/frame/frame.go | |
parent | 8d45daf52a46b8b2cd496c9e885a1ac6d78007e3 (diff) | |
download | go-git-41e5a1ff6f16ec13fa1cebe6e1d872bfe0951cee.tar.gz |
add merkletrie iterator and its helper frame type (#252)
* add merkletrie iterator and its helper frame type
* requested changes by mcuadros
* reuqested changes: smola
Diffstat (limited to 'utils/merkletrie/internal/frame/frame.go')
-rw-r--r-- | utils/merkletrie/internal/frame/frame.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/utils/merkletrie/internal/frame/frame.go b/utils/merkletrie/internal/frame/frame.go new file mode 100644 index 0000000..fd06307 --- /dev/null +++ b/utils/merkletrie/internal/frame/frame.go @@ -0,0 +1,91 @@ +package frame + +import ( + "bytes" + "fmt" + "sort" + "strings" + + "srcd.works/go-git.v4/utils/merkletrie/noder" +) + +// A Frame is a collection of siblings in a trie, sorted alphabetically +// by name. +type Frame struct { + // siblings, sorted in reverse alphabetical order by name + stack []noder.Noder +} + +type byName []noder.Noder + +func (a byName) Len() int { return len(a) } +func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byName) Less(i, j int) bool { + return strings.Compare(a[i].Name(), a[j].Name()) < 0 +} + +// New returns a frame with the children of the provided node. +func New(n noder.Noder) (*Frame, error) { + children, err := n.Children() + if err != nil { + return nil, err + } + + sort.Sort(sort.Reverse(byName(children))) + return &Frame{ + stack: children, + }, nil +} + +// String returns the quoted names of the noders in the frame sorted in +// alphabeticall order by name, surrounded by square brackets and +// separated by comas. +// +// Examples: +// [] +// ["a", "b"] +func (f *Frame) String() string { + var buf bytes.Buffer + _ = buf.WriteByte('[') + + sep := "" + for i := f.Len() - 1; i >= 0; i-- { + _, _ = buf.WriteString(sep) + sep = ", " + _, _ = buf.WriteString(fmt.Sprintf("%q", f.stack[i].Name())) + } + + _ = buf.WriteByte(']') + + return buf.String() +} + +// First returns, but dont extract, the noder with the alphabetically +// smaller name in the frame and true if the frame was not empy. +// Otherwise it returns nil and false. +func (f *Frame) First() (noder.Noder, bool) { + if f.Len() == 0 { + return nil, false + } + + top := f.Len() - 1 + + return f.stack[top], true +} + +// Drop extracts the noder with the alphabetically smaller name in the +// frame or does nothing if the frame was empty. +func (f *Frame) Drop() { + if f.Len() == 0 { + return + } + + top := f.Len() - 1 + f.stack[top] = nil + f.stack = f.stack[:top] +} + +// Len returns the number of noders in the frame. +func (f *Frame) Len() int { + return len(f.stack) +} |