Files
weave-scope/report/node_set.go
2016-01-19 16:31:08 +00:00

95 lines
2.3 KiB
Go

package report
import (
"sort"
)
// NodeSet is a sorted set of nodes keyed on (Topology, ID). Clients must use
// the Add method to add nodes
type NodeSet []Node
// MakeNodeSet makes a new NodeSet with the given nodes.
func MakeNodeSet(nodes ...Node) NodeSet {
if len(nodes) <= 0 {
return nil
}
result := make(NodeSet, len(nodes))
copy(result, nodes)
sort.Sort(result)
for i := 1; i < len(result); { // remove any duplicates
if result[i-1].Equal(result[i]) {
result = append(result[:i-1], result[i:]...)
continue
}
i++
}
return result
}
// Implementation of sort.Interface
func (n NodeSet) Len() int { return len(n) }
func (n NodeSet) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
func (n NodeSet) Less(i, j int) bool { return n[i].Before(n[j]) }
// Add adds the nodes to the NodeSet. Add is the only valid way to grow a
// NodeSet. Add returns the NodeSet to enable chaining.
func (n NodeSet) Add(nodes ...Node) NodeSet {
for _, node := range nodes {
i := sort.Search(len(n), func(i int) bool {
return n[i].Topology >= node.Topology && n[i].ID >= node.ID
})
if i < len(n) && n[i].Topology == node.Topology && n[i].ID == node.ID {
// The list already has the element.
continue
}
// It a new element, insert it in order.
n = append(n, Node{})
copy(n[i+1:], n[i:])
n[i] = node
}
return n
}
// Merge combines the two NodeSets and returns a new result.
func (n NodeSet) Merge(other NodeSet) NodeSet {
switch {
case len(other) <= 0: // Optimise special case, to avoid allocating
return n // (note unit test DeepEquals breaks if we don't do this)
case len(n) <= 0:
return other
}
result := make([]Node, 0, len(n)+len(other))
for len(n) > 0 || len(other) > 0 {
switch {
case len(n) == 0:
return append(result, other...)
case len(other) == 0:
return append(result, n...)
case n[0].Before(other[0]):
result = append(result, n[0])
n = n[1:]
case n[0].After(other[0]):
result = append(result, other[0])
other = other[1:]
default: // equal
result = append(result, other[0])
n = n[1:]
other = other[1:]
}
}
return result
}
// Copy returns a value copy of the NodeSet.
func (n NodeSet) Copy() NodeSet {
if n == nil {
return n
}
result := make(NodeSet, len(n))
for i, node := range n {
result[i] = node
}
return result
}